2014-11-03 3 views
1

스크립트를 사용하여 PHP에서 cURL을 사용하여 서버에서 JPG, PNG 또는 PPT (x) 파일을 클라이언트로 성공적으로 다운로드합니다. 그러나이 방법으로 저장 한 PowerPoint 파일 중 하나를 열면 "PowerPoint에서 FILENAME.pptx의 내용에 문제가 있음을 발견했습니다 .Powerpoint가 프레젠테이션을 복구하려고 시도 할 수 있습니다.이 프레젠테이션의 원본을 신뢰하는 경우 복구를 클릭하십시오. . "PHP를 사용하는 cURL : 클라이언트에 파일을 다운로드하여 결과가 약간 잘못됨

function download_file($linkRequested = '', $whichFileToDownload = '') 
{ 
    // literal dam reference. We dont want wider access to our files. 
    $fileWithPath = $_SERVER['HTTP_HOST'] . '/files/xxxXXX/specific/' . $whichFileToDownload; 

    /*** define the file type for the download MT ***/ 
    // set generic mime type, in case we don't match 
    $mimeType = 'application/octet-stream'; 
    // JPG 
    if (preg_match('|\.jpg$|i', $whichFileToDownload)) { 
     $mimeType = 'IMAGETYPE_JPEG'; 
    } 
    // PNG 
    if (preg_match('|\.png$|i', $whichFileToDownload)) { 
     $mimeType = 'IMAGETYPE_PNG'; 
    } 
    // older PowerPoint 
    if (preg_match('|\.ppt$|i', $whichFileToDownload)) { 
     $mimeType = 'application/vnd.ms-powerpoint'; 
    } 
    // PowerPoint 
    if (preg_match('|\.pptx$|i', $whichFileToDownload)) { 
     $mimeType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; 
    } 

    /*** do curl MT ***/ 
    $ch = curl_init($fileWithPath); 
    curl_setopt($ch, CURLOPT_URL, $fileWithPath); 

    $fp = fopen($fileWithPath, 'wb'); 

    // set the curl options. Order is important. 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_FILE, $fp); 

    // get the contents of the file as text 
    $content = curl_exec($ch); 

    // describe the file header for the client 
    header('Content-Description: File Transfer'); 
    // set mime type for download of binary data 
    header('Content-Type: ' . $mimeType); 
    // Attachment indicates save the file. Filename sets file name 
    header('Content-Disposition: attachment; filename="' . $whichFileToDownload . '"'); 
    header('Content-Transfer-Encoding: binary'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Pragma: public'); 
    header('Content-Length: ' . strlen($content)); 

    // send the file 
    ob_clean(); 
    flush(); 
    echo $content; 

    // clean up loose ends 
    flush(); 
    curl_close($ch); 
    fclose($fp); 

    // don't return anything 
} 

스트림을 올바르게 닫지 않았습니까? 나는 그 문제가 뭔지 모른다.

참고 : JPG 및 PNG 파일이 정상적으로 열립니다. & "복구"를 클릭하면 파일이 성공적으로 열립니다.

+0

나는'filename = " '. $ whichFileToDownload"''를 기대한다고 가정 할 때, 당신의 내용 처분에 오류가 있다고 말할 것이다. 그러나 당신은''' 값. – Ohgodwhy

+1

다른 서버를 찾을 수 없습니다. 스크립트가 실행되는 서버와 동일한 서버에서 파일을 다운로드하려고합니다. ['readfile ($ filename)'] (http : // php. net/manual/en/function.readfile.php) 파일을 cURL을 통해 변수로로드하는 대신 스트리밍합니다. 또한 정규 표현식이 파일 확장자와 일치합니다. 그들은 '/ \. jpg $/i' (리터럴 기간, 문자열 끝에 만 일치)와 같아야합니다. – Stecman

+0

은 파일의 이전/이후 버전을 비교합니다. 16 진 편집기 또는 2 진 diff에로드하십시오. 아마도 파일의 시작 부분이나 끝 부분에서 아마도 PHP 오류/경고 또는 "fluff"를 발견하게 될 것입니다. –

답변

1

스크립트에서 파일 다운로드를 철저히 관리하는 것은 좋은 생각이 아닙니다. 아파치에 대한 x_sendfile 모드 : 파일이 웹 서버에 있기 때문에 좀 더 강력한 접근 방식 등을 사용하는 경우 그것은 더 나은

https://tn123.org/mod_xsendfile/심판

사용법 :

header("X-Sendfile: $path_to_somefile"); 
    header("Content-Type: application/octet-stream"); 
    header("Content-Disposition: attachment; filename=\"$somefile\""); 
    exit; 

또한, 스크립트와 다운로드를 일시 중지하고 다시 시작할 수있는 가능성을 포기하고 있습니다 (RangeContent-Range 헤더를 수동으로 관리해야하며 오류가 발생하기 쉽습니다).

+1

흥미 롭습니다. 전에는 들어 본 적이 없었습니다. 여기에 x_sendfile이 무엇인지/그들이 관심있는 사람들을 위해 어떻게 작동하는지에 대한 더 나은 설명이 있습니다 : http://www.yiiframework.com/wiki/129/x-sendfile-serve-large-static-files-efficiently-from-web-applications/ – Mike

+1

(IIS를 사용하기 때문에 아파치 개조가 도움이되지 않습니다.)하지만 제 동기 부여가 있어야한다고 생각합니다. 다운로드 용 JPG 및 PNG 파일은 IE8 +에서 'download'href 속성에 대한 규격을 준수하지 않아서 강제로 볼 수 있습니다. 그래서 필터링 에이전트가 덜 신뢰할 수 있기 때문에 모든 브라우저에서 다운로드 할 수 있도록이 도구를 만들었습니다. 하지만 PPT가 IE8 +의 강제보기 기능의 영향을받지 않음을 알게되었습니다. 따라서이 스크립트를 이미지에만 사용하여 문제를 피할 수 있습니다. 감사합니다. 직접 도와주지 않았지만 도움이되었습니다. – Whatevah

관련 문제