我目前正在使用允許分塊下載/上傳二進制文件(應允許更大文件)的外部SOAP Web服務。我需要允許最終用戶使用我的PHP應用程序通過瀏覽器下載文件。提供小文件效果很好,但25MB +文件會導致Web服務器耗盡內存。通過PHP從外部Web服務流式傳輸大文件
我正在使用原生PHP Soap Client(無MTOM支持),並通過提交表單來請求下載。目前,似乎Web服務器在向瀏覽器輸出任何內容之前嘗試下載整個文件(例如,直到整個文件通過PHP進行處理之後,「下載」提示纔會顯示)。
我的方法看起來像這樣(抱歉,如果它很混亂,我已經在這個問題上一段時間了)。
public function download()
{
$file_info_from_ws ... //Assume setup from $_REQUEST params
//Don't know if these are needed
gc_enable();
set_time_limit(0);
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
//File Info
$filesize = $file_info_from_ws->get_filesize();
$fileid = $file_info_from_ws->get_id();
$filename = $file_info_from_ws->get_name();
$offset = 0;
$chunksize = (1024 * 1024);
//Clear any previous data
ob_clean();
ob_start();
//Output headers
header('Content-Type: application/octet-stream');
header('Content-Length: ' . $filesize);
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Accept-Ranges: bytes');
while($offset < $filesize)
{
$chunk = $this->dl_service()->download_chunked_file($fileid, $offset, $chunksize);
if($chunk)
{
//Immediately echo out the stream
$chunk->render();
$offset += $chunksize;
unset($chunk); //Shouldn't this trigger GC?
ob_flush();
}
}
ob_end_flush();
}
所以我的主要問題是: 什麼是從外部資源(web服務,數據庫等),通過PHP向最終用戶輸出的大型二進制數據塊的最佳方式?最好不要殺死內存/ CPU太多。
我也很好奇如下:
爲什麼不第一輸出後的下載提示彈出?
爲什麼在about方法的每個循環之後內存不會被釋放?
的fopen可以打開外部URL。所以它應該在理論上起作用。 – DampeS8N 2010-12-09 19:20:18
不幸的是,API不能直接由URL調用。因爲WebService是一個非常複雜的enterprise-y SOAP服務,並且download_chunk方法實際上需要相當複雜的對象作爲參數。 – 2010-12-09 19:27:52