私はfile_get_contents()
を使用して、7M(7〜30M)を超えるファイルを読み取ります。そして、私はクライアントにそれをダウンロードさせるためにそれをエコーします。PHP:なぜ16KB(16624バイト)のファイルしかダウンロードできないのですか?
注:これらのファイルをダウンロードするための直接リンクはありません。だから私はそれをPHPに読み込んでダウンロードファイルを作成しなければなりません。大きなファイルをメモリに読み込むことは間違った考えです---ファイルを直接ダウンロードすることが最善の方法です。しかし今はそうではありません...ファイルは他人によって作成され、クラウドファイルサーバーに移動する計画はありません。 ---私はそれをPHPで処理する必要があります。
何か不自由なことがあります。私の個人的なPHP7ドッカーコンテナでうまくいきます(設定ファイルはhttps://github.com/AarioAi/Confです)
私はフルファイル(おそらく7.8M)をダウンロードできます。
しかし、私はこれらのコードをPHPとNginxの設定とほぼ同じ別のサーバ(PHP 5.5)にプッシュします。このファイルは16KB(16624B)しかダウンロードできません。
"HTTP_RANGE": null,
"Content-Length:": 7490833,
"md5": "aaefc8249e2a96574fa7b83e7bc168f0",
"fileSize": 7490833
16キロバイトのセグメントは、元のファイルの一部であるかどうかを確認するために:
ここで7.8Mバイナリファイルに関するデバッグ情報です。私は繰り返される文字列 "Hello、Aario"で16Mファイルを埋めます。シェルスクリプトによって。次に、ダウンロードした16KBセグメントをPHP 5.5サーバから開きます。それらはすべて "Hello、Aario。Hello、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ファイル間には大きな違いはないことに気付きました。
私はタイムアウトしていると思います。私は別のサーバ(PHP 5.5)のNginx keepalive_timeout
をチェックしていますが、それはこのサーバ(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);
}
のob_start()...あなたはそれをグーグルことができます。
出力にファイルをストリーミングするためのより良い方法はこれです。クライアントがHTTP_RANGEを送信できるようにしたい。 – AarioAi
私のポイントは: 'ob_start();'、 'ob_end_clean();'の直後には何もありません。あなたはそれを残すことができ、結果は同じになります。 'HTTP_RANGE'に関して:私のコードは簡単な例ですが、あなたが望むならそれを拡張することができます。 –
私は前にfopenを試みましたが、 'echo $ content'と同じでした。大きなファイルをメモリに読み込むのは間違った考えです---ファイルを直接ダウンロードするリンクを作るのが最善の方法です。しかし今はそうではありません...ファイルは他人によって作成され、クラウドファイルサーバーに移動する計画はありません。 ---私はそれをPHPで処理する必要があります。私はfpassthruを試しました、それは同じですが、わずか16KBはPHP 5.5サーバからダウンロードできますが、PHP7からは7.8Mです。 – AarioAi