복붙노트

파일 다운로드를위한 HTTP 헤더

PHP

파일 다운로드를위한 HTTP 헤더

필자는 파일 다운로드를 처리하고 요청 된 파일을 확인하고 적절한 HTTP 헤더를 설정하여 브라우저에서 파일을 실제로 다운로드하도록 (브라우저에 표시하는 대신) 트리거하는 PHP 스크립트를 작성했습니다.

일부 사용자가 특정 파일이 잘못 식별되었다는보고가있었습니다 (확장명에 상관없이 브라우저는 GIF 이미지로 간주합니다). 나는 응답 헤더에 "Content-type"을 설정하지 않았기 때문에 이것이라고 생각합니다. 이럴 가능성이 가장 높습니까? 그렇다면 가능한 모든 파일 형식을 고려하지 않고 모든 파일에 사용할 수있는 상당히 일반적인 형식이 있습니까?

현재 나는 "Content-disposition : attachment; filename = arandomf.ile"이라는 값만 설정하고 있습니다.

업데이트 : 파일 다운로드 (http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/)에 대한보다 강력한 프로세스를 구축하기 위해이 가이드를 여기 따라 왔습니다. 스크립트가 실행될 때와 브라우저의 다운로드 대화 상자가 나타날 때 사이에 상당한 지연이 있습니다. 누구든지이 문제를 일으키는 병목 현상을 식별 할 수 있습니까?

내 구현은 다음과 같습니다.

/**
 * Outputs the specified file to the browser.
 *
 * @param string $filePath the path to the file to output
 * @param string $fileName the name of the file
 * @param string $mimeType the type of file
 */
function outputFile($filePath, $fileName, $mimeType = '') {
    // Setup
    $mimeTypes = array(
        'pdf' => 'application/pdf',
        'txt' => 'text/plain',
        'html' => 'text/html',
        'exe' => 'application/octet-stream',
        'zip' => 'application/zip',
        'doc' => 'application/msword',
        'xls' => 'application/vnd.ms-excel',
        'ppt' => 'application/vnd.ms-powerpoint',
        'gif' => 'image/gif',
        'png' => 'image/png',
        'jpeg' => 'image/jpg',
        'jpg' => 'image/jpg',
        'php' => 'text/plain'
    );

    $fileSize = filesize($filePath);
    $fileName = rawurldecode($fileName);
    $fileExt = '';

    // Determine MIME Type
    if($mimeType == '') {
        $fileExt = strtolower(substr(strrchr($filePath, '.'), 1));

        if(array_key_exists($fileExt, $mimeTypes)) {
            $mimeType = $mimeTypes[$fileExt];
        }
        else {
            $mimeType = 'application/force-download';
        }
    }

    // Disable Output Buffering
    @ob_end_clean();

    // IE Required
    if(ini_get('zlib.output_compression')) {
        ini_set('zlib.output_compression', 'Off');
    }

    // Send Headers
    header('Content-Type: ' . $mimeType);
    header('Content-Disposition: attachment; filename="' . $fileName . '"');
    header('Content-Transfer-Encoding: binary');
    header('Accept-Ranges: bytes');

    // Send Headers: Prevent Caching of File
    header('Cache-Control: private');
    header('Pragma: private');
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');

    // Multipart-Download and Download Resuming Support
    if(isset($_SERVER['HTTP_RANGE'])) {
        list($a, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
        list($range) = explode(',', $range, 2);
        list($range, $rangeEnd) = explode('-', $range);

        $range = intval($range);

        if(!$rangeEnd) {
            $rangeEnd = $fileSize - 1;
        }
        else {
            $rangeEnd = intval($rangeEnd);
        }

        $newLength = $rangeEnd - $range + 1;

        // Send Headers
        header('HTTP/1.1 206 Partial Content');
        header('Content-Length: ' . $newLength);
        header('Content-Range: bytes ' . $range - $rangeEnd / $size);
    }
    else {
        $newLength = $size;
        header('Content-Length: ' . $size);
    }

    // Output File
    $chunkSize = 1 * (1024*1024);
    $bytesSend = 0;

    if($file = fopen($filePath, 'r')) {
        if(isset($_SERVER['HTTP_RANGE'])) {
            fseek($file, $range);

            while(!feof($file) && !connection_aborted() && $bytesSend < $newLength) {
                $buffer = fread($file, $chunkSize);
                echo $buffer;
                flush();
                $bytesSend += strlen($buffer);
            }

            fclose($file);
        }
    }
}

해결법

  1. ==============================

    1.RFC 2046 (다목적 인터넷 메일 확장)에 따르면 :

    RFC 2046 (다목적 인터넷 메일 확장)에 따르면 :

    그래서 나는 그걸로 갈거야.

  2. ==============================

    2.Alex의 링크가 설명했듯이 Content-Type 상단에 Content-Disposition 헤더가 누락되었을 수 있습니다.

    Alex의 링크가 설명했듯이 Content-Type 상단에 Content-Disposition 헤더가 누락되었을 수 있습니다.

    이렇게 뭔가 :

    Content-Disposition: attachment; filename=MyFileName.ext
    
  3. ==============================

    3.이 강제 다운로드 스크립트를 사용해 볼 수 있습니다. 당신이 그것을 사용하지 않더라도, 그것은 아마도 올바른 방향으로 당신을 가리킬 것입니다 :

    이 강제 다운로드 스크립트를 사용해 볼 수 있습니다. 당신이 그것을 사용하지 않더라도, 그것은 아마도 올바른 방향으로 당신을 가리킬 것입니다 :

    <?php
    
    $filename = $_GET['file'];
    
    // required for IE, otherwise Content-disposition is ignored
    if(ini_get('zlib.output_compression'))
      ini_set('zlib.output_compression', 'Off');
    
    // addition by Jorg Weske
    $file_extension = strtolower(substr(strrchr($filename,"."),1));
    
    if( $filename == "" ) 
    {
      echo "<html><title>eLouai's Download Script</title><body>ERROR: download file NOT SPECIFIED. USE force-download.php?file=filepath</body></html>";
      exit;
    } elseif ( ! file_exists( $filename ) ) 
    {
      echo "<html><title>eLouai's Download Script</title><body>ERROR: File not found. USE force-download.php?file=filepath</body></html>";
      exit;
    };
    switch( $file_extension )
    {
      case "pdf": $ctype="application/pdf"; break;
      case "exe": $ctype="application/octet-stream"; break;
      case "zip": $ctype="application/zip"; break;
      case "doc": $ctype="application/msword"; break;
      case "xls": $ctype="application/vnd.ms-excel"; break;
      case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
      case "gif": $ctype="image/gif"; break;
      case "png": $ctype="image/png"; break;
      case "jpeg":
      case "jpg": $ctype="image/jpg"; break;
      default: $ctype="application/force-download";
    }
    header("Pragma: public"); // required
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false); // required for certain browsers 
    header("Content-Type: $ctype");
    // change, added quotes to allow spaces in filenames, by Rajkumar Singh
    header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($filename));
    readfile("$filename");
    exit();
    
  4. from https://stackoverflow.com/questions/386845/http-headers-for-file-downloads by cc-by-sa and MIT license