【问题标题】:How to start the download of remote big files directly?如何直接开始下载远程大文件?
【发布时间】:2013-05-16 09:03:14
【问题描述】:

我正在尝试将一个大文件从外部 API 传递给用户,(考虑 100MB 或更多)

目前,我正在使用一些偏执的脚本(由于过去的故障)来尽快下载脚本。

“下载”仅指浏览器上的下载触发器,而不是文件的实际下载。只是用户可以选择他想要保存文件的位置。

set_time_limit(0);

apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);
ini_set('output_buffering', 0);
ini_set('implicit_flush', 1);
for($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);

header('Content-Description: File Transfer');
header('Content-type: application/octet-stream');
header('Content-Transfer-Encoding: Binary');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Cache-Control: private');

ob_flush();
flush();

$fh = fopen($external_api_url, 'rb');
while(!feof($fh))
{
    echo fread($fh, 512);
    ob_flush();
    flush();
}
fclose($fh);

使用此脚本,50mb 的文件仍然需要 20 秒才能显示下载弹出窗口,而更大的文件则需要更长的时间。

有什么方法可以更快地开始直播吗?

编辑: 我也尝试过 fpassthru() 和 readfile() 但对于同一个 50mb 文件需要 40 秒,这让我觉得这种方式更好。我也玩过不同的读取大小(512、256、64,还有其他几个),但我没有注意到差异)

【问题讨论】:

  • 如果您有 PHP 5,您是否尝试过 $contents = stream_get_contents($fh); echo $contents;file_get_contents(...) 而不是您的 while 循环?此外,fread() 实际上鼓励您一次读取 8192 个字节,因为那是块大小。
  • @Arthur 在将整个文件发送给用户之前,stream_get_contents 和 file_get_contents 不会等待在 PHP 中下载整个文件吗?此外,我不知道 8192 bute 块的大小,这可以解释为什么我尝试的不同值(都在这个数字之下)给出了相同的结果。有没有办法降低块大小?

标签: php stream download fopen


【解决方案1】:

您的浏览器需要很长时间才能触发下载对话框的原因是 API 需要很长时间才能返回其第一个数据块,例如,它们可能在开始发送之前将整个文件读入内存数据给你,这可以解释为什么更长的文件需要更长的时间才能启动,即使你总是尽可能快地写入前 512 个字节。

我尝试通过从本地文件读取来在本地模拟它,但在您的 while 循环之前有一个 sleep(5); 语句。

通过省略header('Content-type: application/octet-stream'); 行,我能够让谷歌浏览器在任何数据之前开始下载,同时在尝试读取文件之前仍发出flush(); 调用。 (你已经在做第二部分了)

但这似乎不适用于 Firefox 3.6,因此您可能需要针对不同浏览器使用不同的噱头,除非您可以预测文件的第一个字符(查看 BOM)并在任何事情之前回显,随后将其从您的第一个 fread() 调用的开头删除。

希望对你有帮助!但基本上外部 API 让你搞砸了。

【讨论】:

  • 自从我不得不为它工作的那一刻起,外部 API 就把我搞砸了。 :P 但是谢谢你的回答,我会尽快尝试并报告:)
  • 它似乎工作得很好,我确实注意到了与 FireFox 相同的问题并省略了 content-type 标头,FireFox 会将其下载为 html 文件,即使它是其他文件......也许我可以发送稍后那个标题...
猜你喜欢
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 2017-01-25
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
相关资源
最近更新 更多