2009-08-06 67 views
0

我的網站使用此代碼下載一個文件:頭的ReadFile

$flv = **filename** 

$ch = curl_init($flv); 
curl_setopt($ch, CURLOPT_NOBODY, true); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here) 
$data = curl_exec($ch); 

curl_close($ch); 
if ($data === false) { 
    echo 'cURL failed'; 
    exit; 
} 

$contentLength = 'unknown'; 
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) { 
    $contentLength = (int)$matches[1]; 
} 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename='.basename($flv)); 
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: ' . $contentLength); 
ob_clean(); 
flush(); 
readfile($flv); 

代碼工作,但是,直到完成下載的鏈接一個頁面都bloqued,等待下載完成!

我該怎麼辦?

+0

你嘗試刪除? ob_clean();和flush(); – 2009-08-06 14:05:47

+0

是的,但沒有結果... – Pedro 2009-08-06 14:06:55

+0

「echo readfile($ flv);」 ? – 2009-08-06 14:10:00

回答

1

嘗試:

$ContentLength = filesize($flv); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename='.basename($flv)); 
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: ' . $ContentLength); 

$fh = fopen($flv, 'r'); 
echo fread($fh, $ContentLength); 
fclose($fh); 
+1

這會將文件下載兩次,這是浪費時間。 – 2009-08-06 14:28:22

+0

那麼我發現一個解決方案,如果我們把session_write_close()放在下載之前,我不會等待下載完成,所以問題解決了。 謝謝! – Pedro 2009-08-06 14:29:45

+0

下載文件兩次?,你檢查一下snifer嗎? – 2009-08-06 14:33:30

1

你如何鏈接到此頁面。當然,下載會阻止頁面上的所有內容,因爲它會彈出一個模式窗口,允許用戶選擇在哪裏下載文件或取消下載。這是一個瀏覽器功能。

如果您在談論別的事情,請解釋一下。


編輯:

哪下載你指的是?這裏有兩個下載。 一個是服務器到服務器使用CURL下載文件。 另一個是HTTP客戶端從您的服務器下載相同的文件。兩者都可以「固定」,但你必須具體。

如果你想CURL下載是自動的,那麼你必須這樣做,下載是一個單獨的過程。不幸的是,PHP只能正常支持一個進程,所以你必須使用非標準的PHP。

可能性:

1)使用命令行

EXEC( 'PHP filename.php downloadfile.ext &');

在這裏您發送PHP腳本filename.php參數download.ext。由於命令結尾的&,整個過程將在後臺執行。 做一個var_dump($ argv);看到通過的參數。

您還可以使用工藝管道做相同的:

如:poopen()proc_open()

他們給你多一點控制。

2)您也可以安裝其中一個過程控制擴展。 http://php.net/manual/en/refs.fileprocess.process.php

這將允許你從你的PHP腳本中分離出一個獨立的進程,它將處理文件下載到你的服務器。還有進程間通信(IPC)擴展,可讓您跟蹤單獨進程中發生的情況。

3)你可以寫一個deamon來處理下載。基本上,您還需要處理deamon中的多個進程,以便一次執行多個下載。你還需要一點IPC或者至少某種形式的併發,所以你不要多次下載相同的資源。這有點複雜,所以我認爲1和2是更好的選擇。


基本上你要做的就是阻止用戶在這裏等待服務器到服務器的下載。

因此,您首先介紹主要的PHP進程(正常的PHP頁面)。 然後你以某種方式分解過程。 讓子進程使用CURL下載文件。與此同時,父PHP過程立即返回給HTTP客戶端。 當孩子完成donwloading時,父進程可以通過IPC或輪詢併發資源(例如下載文件的文件名(或文件大小或鎖))知道。然後,它將它服務於HTTP客戶端。


如果您的問題與HTTP客戶端有關,那麼您必須查看瀏覽器解決方案。鑑於您正在測試的確切瀏覽器等,等等將會提供有關該問題的信息。