【问题标题】:Problem serving large (image?) files to Safari向 Safari 提供大(图像?)文件时出现问题
【发布时间】:2011-07-07 16:50:47
【问题描述】:

服务器设置:Apache 2.2.14、PHP 5.3.1

我使用 PHP 脚本来提供所有类型的文件,作为具有复杂访问权限的应用程序的一部分。到目前为止,一切进展顺利,但我们的一位测试版用户用 10 兆像素的数码相机拍了一张照片并上传了它。它位于 9 MB 以北的某个地方,9785570 字节。

出于某种原因,在 Safari 中(到目前为止,仅在 Safari 中,我已在 5.0.5 上复制了此内容)下载有时会中途挂起并且永远不会完成。 Safari 只是继续愉快地尝试永远加载。我无法始终如一地重现该问题 - 如果我一遍又一遍地重新加载,有时下载会完成,有时不会。没有明显的规律。

我正在监视服务器访问日志,在 Safari 挂起的情况下,我在离开页面或取消页面加载后看到相应文件大小的 200 响应,但之前没有。

这是为文件提供服务的代码,包括标题。当下载成功并检查标题浏览器端时,我看到内容类型和大小已正确设置。我的标题中有什么吗? Safari中的东西?两个都?

header('Content-Type: ' . $fileContentType);
header('Content-Disposition: filename=' . basename($fpath));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($fpath));
ob_clean();
flush();
session_write_close();
readfile($fpath);
exit;

作为事件保证的其他公告:

通过人为地将下载速度限制为 256k/s -- 即将文件分成 256k 块并在提供它们之间暂停,如

$chunksize = 1 * (256 * 1024); // how many bytes per chunk 
if ($size > $chunksize) { 
  $handle = fopen($fpath, 'rb'); 
  $buffer = ''; 
  while (!feof($handle)) { 
    $buffer = fread($handle, $chunksize); 
    echo $buffer; 
    ob_flush(); 
    flush();
    sleep(1); 
  } 
  fclose($handle); 
} else { 
  readfile($fpath); 
}

我能够保证图像文件在任意条件下都能在 Safari 中成功显示。

512k 的块大小并不能保证显示成功。

我几乎可以肯定这里的问题是 Safari 的图像渲染器无法更快地处理传入的数据,但是:

  • 我很想知道
  • 我还想知道是否有其他类型的解决方法,例如特殊的 CSS webkit 属性或任何处理大图像的方法,因为 256k/秒对于 10 MB 文件来说有点可怕。

更奇怪的是,使用 usleep() 设置更细粒度的睡眠会导致睡眠时间为 500 毫秒而不是 750 毫秒时出现问题。

【问题讨论】:

  • 您是否尝试(重新)将 php 执行超时 (php.net/manual/en/function.set-time-limit.php) 设置为较大的值以排除执行时间作为潜在问题?
  • 是的。当时间限制设置为 300 时,Safari 仍然行为不端,但在我的连接上,文件只需要一两秒即可提供服务。

标签: php apache safari download


【解决方案1】:

我做了一些挖掘,发现没有什么具体的,但我确实看到很多人断言 Safari 在遵守缓存控制指令方面存在问题。一个人断言:

您不需要所有这些缓存控件,只需在过去设置过期时间的 max-age,即可完成您使用的所有这些标头所做的所有事情 [...] 您使用的许多缓存控件标头会导致 Safari 出现问题[...] 最后,一些浏览器不理解文件名,这是唯一可以理解的名称,它必须包含在 Content-Type 标题行中,从不包含在 Content-Disposition 行中。 [...]

(请参阅线程中的最后一篇文章:http://www.codingforums.com/archive/index.php/t-114251.html 旧信息,但你永远不知道......)

所以可能会注释掉你的一些标题,看看是否有改进。

(轶事)我还看到一些较早的帖子抱怨 safari 通过将整个文件附加到部分文件的末尾来恢复中断的下载,以及无休止的下载,这似乎计算了超出发送文件长度的字节数。 (轶事)

【讨论】:

  • 不,即使我完全剥离过期、缓存控制和杂注,它仍然会脱落。
【解决方案2】:

您可能想在读入文件时尝试“分块”文件。

在 PHP.net 上有很多帖子解释了如何做到这一点:http://php.net/manual/en/function.readfile.php

试试:

ob_start();
readfile($path);
$buffer = ob_get_clean();

echo $buffer;

【讨论】:

  • 谢谢,但这没有用。即使我使用代码一次将其分块,Safari 仍然挂在我身上。
  • 把整件事都放进记忆里,嗯?我想说这有效,而且通常有效,但由于某种原因,当 Safari 首次加载页面时,它仍然会出现问题。
猜你喜欢
  • 1970-01-01
  • 2017-10-21
  • 2011-07-29
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多