2016-06-24 8 views
1

Я использую file_get_contents(), чтобы прочитать файл размером более 7M (7 - 30M). И затем я повторяю это, чтобы позволить клиенту загрузить его.PHP: Почему я могу только загрузить 16 КБ (16624 байта) из файлов О 8М с помощью PHP echo?

Примечание: ссылки для скачивания этих файлов отсутствуют. Поэтому я должен прочитать его в PHP и сделать файл загрузки. Прочитать большой файл в памяти - это абсолютно неправильная идея. Лучший способ - сделать файл ссылкой для загрузки. Но не сейчас ... Coz файл создается другими, и у них нет плана переместить их на наши серверы облачных файлов. --- Поэтому я должен обрабатывать его с помощью PHP.

Есть что-то внятное. Он хорошо работает на моем личном контейнере для док-станции PHP7 (конфигурационный файл находится здесь: https://github.com/AarioAi/Conf)

Я могу скачать полный файл (возможно, 7.8M).

Но когда я нажимаю эти коды на другой сервер (PHP 5.5), который имеет почти те же конфигурации PHP и Nginx. Я могу загрузить только 16 КБ (16624В) этого файла.

Вот отладочная информация о бинарном файле 7.8m:

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

Для того, чтобы проверить сегмент 16KB, является ли частью исходного файла. Я заполняю 16M-файл повторяющейся строкой «Hello, Aario». по сценарию оболочки. Затем я открываю загруженный сегмент 16 КБ с сервера PHP 5.5. Все они «Привет, Аари. Привет, Аари. .....»

Итак, 16 КБ определенно является сегментом исходного файла.

Вот отладочная информация о 16М «Здравствуй, Aario.»:

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

Я ничего не посылаем к ob_xxx, так что я думаю, что нет ничего плохого в output_buffering конфигурации. Конфигурации PHP memory_limit одинаковы на обоих серверах. И я также замечаю, что между файлами php-fpm.conf нет существенных различий.

Я думаю, это может быть перерыв. Я проверяю Nginx keepalive_timeout на другом сервере (PHP 5.5), это 65, который длиннее, чем на этом сервере (PHP 7).

Так вы могли бы дать мне несколько советов?

//--------------------------------------------------------------------- 
$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() ... Вы можете Google это.И я хочу разрешить клиенту отправлять HTTP_RANGE. – AarioAi

+0

Моя точка зрения: 'ob_start();', за которым сразу следует 'ob_end_clean();', ничего не делает. Вы можете оставить это, и результат будет таким же. Что касается 'HTTP_RANGE': мой код является коротким примером, вы можете его расширять в любом случае. –

+0

Я пробовал fopen раньше, но это было так же, как 'echo $ content'. Прочитать большой файл в памяти - это абсолютно неверная идея. Лучший способ - сделать файл ссылкой на ссылку. Но не сейчас ... Coz файл создается другими, и у них нет плана переместить их на наши серверы облачных файлов. --- Поэтому я должен обрабатывать его с помощью PHP. Я пробовал fpassthru, это то же самое, только 16 КБ можно скачать с сервера PHP 5.5, а 7.8M из PHP7. – AarioAi

 Смежные вопросы

  • Нет связанных вопросов^_^