2
CDNにファイルが保存されています。ファイルは最大100 MBにすることができるので、私は単純なチャンク方式(下記)を使用しています。Laravel:response() - > stream()を使用して外部ファイルをランダムにダウンロードすると、ダウンロードが破損する
ダウンロードは機能しますが、一部のファイル(ほとんどPDF-s)が壊れてしまい、開くことができません。
誰かがコード内に瑕疵や落とし穴を指摘できますか?
私が考えることの1つは、ヘッダーが何らかの形で時間内に送信されないということです。もう1つは、ファイルのいくつかがUTF-8で保存されていないことで、ファイルを完全に読み取る際に問題が発生する可能性があることです。私は立ち往生している。 (stream()を使用して)
ダウンロードロジック:
$url = 'http://example.com/files/example.pdf';
$headers = array(
'Pragma' => 'public',
'Expires' => '0',
'Content-Transfer-Encoding' => 'binary',
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment; filename="example.pdf"'
);
return response()->stream(function() use ($url) {
$this->readfileChunked($url);
},200, $headers);
チャンキング:
/**
* Serves the given file in chunks.
* Source: http://cn2.php.net/manual/en/function.readfile.php#52598
*
* @param $filename
* @param bool $retbytes
*
* @return bool|int
*/
public function readfileChunked($filename, $retbytes = true) {
$chunkSize = 1024 * 1024; // Size (in bytes) of tiles chunk
$cnt = 0;
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, $chunkSize);
echo $buffer;
ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return number of bytes delivered like readfile() does
}
return $status;
}