duangou2046 2011-07-07 16:50
浏览 44

向Safari提供大(图像?)文件的问题

Server setup: Apache 2.2.14, PHP 5.3.1

I use a PHP script to serve files of all types as part of an application with complex access permissions. Things have worked out pretty well so far, but then one of our beta users took a picture with a 10-megapixel digital camera and uploaded it. It's somewhere north of 9 MB, 9785570 bytes.

For some reason, in Safari (and thus far ONLY in Safari, I've reproduced this on 5.0.5) the download will sometimes hang partway through and never finish. Safari just keeps on merrily trying to load forever. I can't consistently reproduce the problem - if I reload over and over sometimes the download will complete and sometimes it won't. There's no apparent pattern.

I'm monitoring the server access logs and in the cases where Safari hangs I see a 200 response of the appropriate filesize after I navigate away from the page, or cancel the page load, but not before.

Here's the code that serves the file, including headers. When the download succeeds and I inspect the headers browser-side I see the content type and size have been set correctly. Is it something in my headers? Something in Safari? Both?

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;

FURTHER BULLETINS AS EVENTS WARRANT:

By artificially throttling download speed to 256k/s -- that is, by chunking the file into 256k pieces and pausing between serving them, as

$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); 
}

I was able to guarantee a successful display of the image file in Safari under arbitrary conditions.

A chunksize of 512k does not guarantee a successful display.

I am almost certain that the problem here is that Safari's image renderer can't handle data coming in any faster, but:

  • I would like to know for certain
  • I would also to know if there's some other kind of workaround like a special CSS webkit property or whatever to handle large images because 256k/second is kind of dire for a 10 MB file.

And just to pile on the weird, setting up a finer-grained sleep with usleep() results in problems at a sleep time of 500 ms but not 750 ms.

  • 写回答

2条回答 默认 最新

  • drn1008 2011-07-07 16:56
    关注

    You might want to try to "chunk" the file while reading it in.

    There a numerous posts here on PHP.net that explain ways to do that: http://php.net/manual/en/function.readfile.php

    Try:

    ob_start();
    readfile($path);
    $buffer = ob_get_clean();
    
    echo $buffer;
    
    评论

报告相同问题?

悬赏问题

  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏