2013-04-02 4 views
3

drupal에 기사와 관련된 각각의 PDF 파일을 표시하려고합니다. 브라우저에 pdf가 렌더링되어 있으면 직접 열어야합니다. 기존 대화 상자가 표시되지 않으면 '열기', '저장'및 '취소'로 사용자가 옵션 중에서 선택할 수 있도록합니다. PDF는 이미지 및 파일과 같은 모든 리소스에 액세스 할 수있는 공개 웹 서버에 있습니다.올바른 경로로 원격 pdf 파일 열기 404

내가 달성하기 위해 사용하고 코드는 다음과 같습니다 :

$pdf_file_name = "http://mysite.com/valid-pdf-file.pdf"; 
drupal_set_header('Content-type: application/pdf'); 
drupal_set_header('Content-Disposition: inline; filename="' . $pdf_file_name 
. '"'); 
$fp = fopen($pdf_file_name, "r"); 
$file_open_timeout = 60; 
if ($fp) { 
    stream_set_timeout($fp, $file_open_timeout); 
    while (!feof($fp)) { 
    echo fread($fp, 65536); 
    flush(); 
    } 
    fclose($fp); 
} 
else { 
    watchdog("pdf logging", "Could not open the file " . $pdf_file_name); 
} 

이 코드는 (내가 작은 것들 10메가바이트 개까지 있었다 가정) 내 초기 PDF 파일의 일부 근무하지만, 많은 실패했습니다 다른 다음과 같은 오류 메시지가있는 파일 :

는 fopen (http://mysite.com/valid-pdf-file.pdf는) : HTTP 요청에 실패했습니다 : 스트림을 열지 못했습니다! HTTP/1.1 404를 찾을 수 없음

브라우저를 통해 해당 파일 http://mysite.com/valid-pdf-file.pdf의 경로를 열면 오류 메시지없이 파일이 직접 렌더링됩니다. 따라서 나는 위의 코드에서 일부 검색을 기반으로 stream_set_timeout을 시도했지만 여전히 존재하는 파일에도 불구하고 404 오류를 지나칠 수는 없습니다. 여기

이의 예 방법과 같을 것이다 열지 못했습니다 URL 중 하나 :

"http://fileservername.com/resources/sitename/2013/03/20/bed6e3de-41bf-4bf9-bed8-d21508eaa8ca/Trouble --Cloud 제요의 optimized.pdf"

또한 URL이 파일 경로를 인코딩하지만 테스트

결과도 다르지 않았다. fopen 및 readfile에 urlencode($pdf_file_name)을 입력했습니다.

더 나아가 이러한 골치 아픈 pdf 파일의 파일/폴더 권한이 제대로 열리는 것과 다르지 만 다른 점이 없음을 확인했습니다.

ob_clean(); 
flush(); 
readfile($pdf_file_name); 
exit(); 

취급이 파일에 대한 또 다른 코드는 다른 사람이 잘 작동하는 동안 번잡 한 PDF 파일 (404)를 반환 동일한 결과를했다. 이 기능 또는 더 나은 구현을 위해 무엇을 놓치고 있는지에 대한 제안은 크게 감사하겠습니다.

+3

실제 URL을 표시하십시오. 문제는 파일 이름에있는 것입니다. 404 오류는 매우 명확합니다. 요청한 위치에 문제가 있습니다. 브라우저는 사용자 입력을 올바르게 URL 인코딩하는 방법을 연구 할 때 훨씬 지능적입니다. 따라서 URL 인코딩이 해결책 일 수 있지만 실제로로드하려는 실제 URL을 볼 필요가 있습니다 (원하는 경우 도메인 이름을 난독화할 수 있음).) – DaveRandom

+0

URL 래퍼가 fopen (http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)에 사용 가능하게 설정되어 있는지 확인하고 서버의 DNS 확인 제대로 작동하는지 - 간단한 명령 줄을 wget http : //pathto.pdf/file 작동합니까? – shannonman

+1

@shannonman 이러한 문제로 인해 HTTP 404가 발생하지 않습니다. URL 래퍼를 사용하지 않으면 오류가 표시되며 DNS가 작동하지 않으면 원격 서버에 연결하여 404 오류가 발생하지 않습니다 응답. – DaveRandom

답변

4

문제는 실제로 URL 인코딩이지만, 그대로 유지해야하는 일부 문자를 이스케이프 처리하기 때문에 전체 문자열을 urlencode() 수 없습니다. 나는이 같은 것을 제안 :

function escape_url($url) 
{ 
    // Check that the input data is sane 
    if (!$parts = parse_url($url)) { 
     return false; 
    } 
    if (!isset($parts['scheme'], $parts['host'])) { 
     return false; 
    } 

    // construct site base URL 
    $result = $parts['scheme'] . '://'; 

    if (isset($parts['user'])) { 
     $result .= $parts['user']; 
     if (isset($parts['pass'])) { 
      $result .= ':' . $parts['pass']; 
     } 
     $result .= '@'; 
    } 

    $result .= $parts['host']; 

    // Normalize path 
    if (!isset($parts['path'])) { 
     // if no path assume domain root 
     $parts['path'] = '/'; 
    } 
    $parts['path'] = preg_split('#/+#', $parts['path']); // split to path components 
    $parts['path'] = array_map(function($part) { // ensure all components are correctly escaped 
     return urlencode(urldecode($part)); 
    }, $parts['path']); 
    $parts['path'] = implode('/', $parts['path']); // reconstruct string 
    $result .= $parts['path']; 

    // parse the query string an rebuild it 
    if (isset($parts['query'])) { 
     parse_str($parts['query'], $query); 
     if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { 
      // undo magic_quotes 
      array_walk_recursive($query, function(&$value) { 
       $value = preg_replace('#\\\\([\'"\\\\\\x00])#', '$1', $value); 
      }); 
     } 
     $result .= '?' . http_build_query($query); 
    } 

    // add document fragment if present 
    if (isset($parts['fragment'])) { 
     $result .= '#' . $parts['fragment']; 
    } 

    return $result; 
} 

$url = 'http://fileservername.com/resources/sitename/2013/03/20/bed6e3de-41bf-4bf9-bed8-d21508eaa8ca/Trouble --Cloud Compendium optimized.pdf'; 
echo escape_url($url); 
// output: 
// http://fileservername.com/resources/sitename/2013/03/20/bed6e3de-41bf-4bf9-bed8-d21508eaa8ca/Trouble+--Cloud+Compendium+optimized.pdf 

See it working

참고 : 이것은 magic_quotes_gpc 구성 옵션에 의해 영향을받는 URL에있을 수있는 쿼리 문자열을 정상화 parse_str()를 사용합니다. 이 옵션은 더 이상 사용되지 않으며 안전하지 않으므로을 비활성화해야하지만이 옵션을 사용하면이 기능의 출력에 영향을 미칩니다. 런타임에이 설정을 조정할 수 없으므로 환경에서 설정이 비활성화되어 있는지 확인해야합니다.

수정 된 경로 구성 요소의 잠재적 인 이중 인코딩을 수정하면 magic_quotes이 문제를 해결할 때 수정되었습니다.이러한 픽스는 클로저를 사용하므로 더 낮은 버전 인 create_function()에 대해서는 PHP 5.3+가 필요하거나 헬퍼 함수로 대체 될 수 있습니다.