2016-06-24 5 views
1

나는 7M (7 - 30M)보다 큰 파일을 읽으려면 file_get_contents()을 사용합니다. 그런 다음 클라이언트가 다운로드 할 수 있도록 표시합니다.PHP : 왜 내가 16 메가 바이트 (16624 바이트)의 파일을 다운로드 할 수 있습니까?

참고 : 이러한 파일을 다운로드하기위한 직접적인 링크는 없습니다. 그래서 나는 그것을 PHP로 읽고 다운로드 파일을 만들어야한다. 큰 파일을 메모리로 읽어들이는 것은 잘못된 아이디어입니다. 가장 좋은 방법은 파일을 다운로드 링크로 만드는 것입니다. 그러나 지금은 아닙니다 ... 파일이 다른 사람들에 의해 만들어지고 파일을 우리의 클라우드 파일 서버로 옮길 계획이 없다는 것을 명심하십시오. --- PHP로 처리해야합니다.

뭔가가 있습니다. 내 개인 PHP7 도커 컨테이너에서 잘 작동합니다 (설정 파일은 https://github.com/AarioAi/Conf입니다)

전체 파일 (아마도 7.8M)을 다운로드 할 수 있습니다.

하지만이 코드를 거의 동일한 PHP와 Nginx 구성을 가진 다른 서버 (PHP 5.5)로 푸시하면됩니다. 이 파일은 16KB (16624B) 만 다운로드 할 수 있습니다.

여기에 7.8M 바이너리 파일에 대한 디버그 정보는 다음과 같습니다 위해

"HTTP_RANGE": null, 
"Content-Length:": 7490833, 
"md5": "aaefc8249e2a96574fa7b83e7bc168f0", 
"fileSize": 7490833 

는 16킬로바이트 세그먼트가 원본 파일의 일부인지 여부를 확인합니다. 반복되는 문자열 인 "Hello, Aario"가있는 16M 파일을 채 웁니다. 쉘 스크립트로. 그런 다음 PHP 5.5 서버에서 다운로드 한 16KB 세그먼트를 엽니 다. 그들은 모두 "Hello, Aario. 안녕하세요, Aario. ....."입니다.

따라서 16KB는 확실히 원본 파일의 세그먼트입니다.

"HTTP_RANGE": null, 
"Content-type": "application/force-download", 
"Content-Length:": 16155228, 
"md5": "5c919dd9d1049a59e7c2a8cb55a695a9", 
"fileSize": 16155228 

내가 ob_xxx에 아무것도 전송하지, 그래서 나는 output_buffering 설정 아무 문제가 없다 생각한다. "안녕하세요, Aario"

다음은 16M에 대한 디버그 정보입니다. PHP memory_limit 구성은 두 서버에서 동일합니다. 그리고 php-fpm.conf 파일 사이에는 큰 차이가 없음을 알았습니다.

시간이 초과되었을 수 있습니다. Nginx keepalive_timeout을 다른 서버 (PHP 5.5)에서 확인하십시오.이 서버 (PHP 7)보다 긴 65입니다.

팁을 주실 수 있습니까?

//--------------------------------------------------------------------- 
$length = (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content)); 
// it's just the sample to calculate Content-Length, actually, 
// it needs be handled in the if (isset($_SERVER['HTTP_RANGE'])) {} 
//---------------------------------------------------------------------- 

if (isset($_SERVER['HTTP_RANGE'])) { 
     header('Accept-Ranges: bytes'); 
     //client sent us a multibyte range, can not hold this one for now 
     if (strpos($_SERVER['HTTP_RANGE'], ',') !== false) { 
      header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); 
    .... 
    .... 
} 



if ($debug > 0) { 
     return [ 
      'Content-type' => $contentType, 
      'Content-Length:' => $length, 
      'md5' => md5_file($file), 
      'fileSize' => $fileSize, 
     ]; 
    } else { 
     header('Pragma: public'); 
     header('Expires: 0'); 
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
     header("Content-Type: $contentType"); 
     header('Content-Length: ' . $length); 
     header("Content-Disposition: attachment; filename=\"$fileName\""); 
     header('Content-Transfer-Encoding: binary'); 
     $content = function_exists('mb_substr') ? mb_substr($content, $contentStart, $length) : substr($content, $contentStart, $length); 
     ob_start(); 
     ob_end_clean(); 
     echo $content; 
     exit(0); 
    } 

답변

1

표시되는 코드 조각이 어떻게 작동하는지 알 수 없습니다. 그렇지 않습니다. 하나는 file_get_contents()입니다. 그리고 이것은 무엇을합니까?

ob_start(); 
    ob_end_clean(); 

아무것도 아니요? 정의되지 않은 변수도 많이 있습니다. 즉, 이것은 나쁜 예입니다.

큰 파일을 file_get_contents()으로 읽은 다음 echo으로 읽는 것은 내 생각에는 좋은 생각이 아닙니다. 전체 파일은 출력으로 보내기 전에 메모리에 저장되고 거기에 저장됩니다. 전통적으로 파일은 항상 청크로 읽은 다음 청크를 출력으로 보냅니다.

// open the file in a binary mode 
$filename = '/mybigfile.huge'; 
$handle = fopen($filename,'rb'); 

if ($handle) 
{ 
    // send the right headers 
    header("Content-Type: ....."); 
    header("Content-Length: " . filesize($filename)); 
    ........ 

    // dump the file to the output 
    fpassthru($handle); 
    // close file 
    fclose($handle); 
} 
+0

위한 ob_start() ... 당신은 그것을 구글 수 있습니다

출력에 파일을 스트리밍 할 수있는 더 좋은 방법이있다.그리고 클라이언트가 HTTP_RANGE를 전송하도록 허용하려고합니다. – AarioAi

+0

내 요점은 :'ob_start();','ob_end_clean();'바로 뒤에 오는 것은 아무 것도하지 않는다. 당신은 그것을 떠날 수 있고 결과는 동일 할 것입니다. 'HTTP_RANGE'에 대해서 : 내 코드는 간단한 예제이며, 어쨌든 원하는대로 확장 할 수 있습니다. –

+0

전에 fopen을 시도했지만,'echo $ content'와 같았습니다. 큰 파일을 메모리로 읽어들이는 것은 잘못된 아이디어입니다. 가장 좋은 방법은 파일을 다운로드 링크로 만드는 것입니다. 그러나 지금은 아닙니다 ... 파일이 다른 사람들에 의해 만들어지고 파일을 우리의 클라우드 파일 서버로 옮길 계획이 없다는 것을 명심하십시오. --- PHP로 처리해야합니다. 나는 fpassthru를 시도했다. PHP 5.5에서 7.8M까지만 16KB 만 다운로드 할 수있다. – AarioAi