2013-06-28 170 views
5

我試圖下載一個.mp4文件。 (大約1.3GB大小)。 我使用的是以下幾點: 強制下載,從PHP文件

<?php 
$path = "video.mp4"; 
header('Accept-Ranges: bytes'); // For download resume 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Content-Description: File Transfer'); 
header('Content-Disposition: attachment; filename="'.basename($path).'"'); 
header('Content-Length: ' . filesize($path)); // File size 
header('Content-Transfer-Encoding: binary'); // For Gecko browsers mainly 
header('Content-Type: application/octet-stream'); 
header('Expires: 0'); 
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT'); 
header('Pragma: no-cache'); 
ob_clean(); 
flush(); 
readfile($path); 

我打開我的PHP文件,而Firefox的「要保存」菜單彈出。尺寸看起來不錯。 我按另存爲,到我的桌面。最終下載的文件按照隨機大小列出,大約爲400MB(330,463和440)。

響應頭:

Connection: Keep-Alive 
Content-Disposition: attachment; filename="//www.frederikspang.dk/elevgallavideo.mp4" 
Content-Length: 1422778850 
Content-Type: video/mp4 
Date: Sun, 30 Jun 2013 22:12:30 GMT 
Keep-Alive: timeout=10, max=50 
Pragma: public 
Server: Apache 
content-transfer-encoding: binary 
+1

您可能會遇到執行時間限制。下載總是在相同的時間段後停止嗎? – 2013-06-28 21:08:46

+0

可恢復的文件下載需要比這更多的代碼;所以你應該刪除'Accept-Ranges'。請參閱:http://stackoverflow.com/questions/157318/resumable-downloads-when-using-php-to-send-the-file –

+0

你實際上使用輸出緩衝?如果不是,你可能不需要ob_clean()和flush(),因爲readfile命令會直接將數據輸出到客戶端。 – dethtron5000

回答

0
<?php 
$filename = "theDownloadedFileIsCalledThis.mp4"; 
$myFile = "/absolute/path/to/my/file.mp4"; 

// Add bellow code for mime type 
$ext=strtolower(substr($fl,strrpos($myFile,"."))); 
$mime_types = array(
      '.txt' => 'text/plain', 
      '.htm' => 'text/html', 
      '.html' => 'text/html', 
      '.php' => 'text/html', 
      '.css' => 'text/css', 
      '.js' => 'application/javascript', 
      '.json' => 'application/json', 
      '.xml' => 'application/xml', 
      '.swf' => 'application/x-shockwave-flash', 
      '.flv' => 'video/x-flv', 

      // images 
      '.png' => 'image/png', 
      '.jpe' => 'image/jpeg', 
      '.jpeg' => 'image/jpeg', 
      '.jpg' => 'image/jpeg', 
      '.gif' => 'image/gif', 
      '.bmp' => 'image/bmp', 
      '.ico' => 'image/vnd.microsoft.icon', 
      '.tiff' => 'image/tiff', 
      '.tif' => 'image/tiff', 
      '.svg' => 'image/svg+xml', 
      '.svgz' => 'image/svg+xml', 

      // video 
      '.3gp' => 'video/3gpp', 
      '.3g2' => 'video/3g2', 
      '.avi' => 'video/avi', 
      '.mp4' => 'video/mp4', 
      '.asf' => 'video/asf', 
      '.mov' => 'video/quicktime', 
     ); 

if (array_key_exists($ext, $mime_types)){ 
    $mm_type=$mime_types[$ext]; 
}else{ 
    $mm_type="application/octet-stream"; 
} 
$mm_type="application/octet-stream"; 

header("Cache-Control: public, must-revalidate"); // Avoid this line 
header("Pragma: public"); // Add this line 
header("Pragma: hack"); // Avoid this line 
header("Content-Type: " . $mm_type); 
header("Content-Length: " .(string)(filesize($myFile))); // Avoid this line 
header('Content-Disposition: attachment; filename="'.$filename.'"'); 
header('Content-Length: ' . filesize($myFile)); // Add this line 
header("Content-Transfer-Encoding: binary\n"); 
ob_clean(); // Add this line 

readfile($myFile); 

?> 
+0

答案很不清楚。它沒有很好地記錄。請詳細說明「避免」和「添加」,以及爲什麼。 –

+0

mime類型的引用是有用的,標題聲明是有意義的。「避免」顯然意味着「不使用」,「添加」意味着「添加」。他可以做的是提供了一個更好的解釋,爲什麼 – zgr024

+0

如果你只是要設置'$ mm_type =「application/octet-stream」',反正所有的MIME類型垃圾? –

1

這是很難 - 30秒後大多數PHP配置將失敗。如果您擁有php.ini,則可以將其更改爲更長的限制。但仍然 - 這是值得嗎?我的意思是 - 文件可能變大或網絡變慢 - 並且再一次您會遇到超時。

這就是爲什麼下載者作了 - 下載較小的塊Half Crazed大文件顯示你的代碼,我THIS答案(它不是隻有一個 - 這只是考慮的方式之一客戶洽談轉讓 - 但仍然是其一個好的開始)。

Mega.co.nz例如使用新的html5功能。在瀏覽器中使用塊下載文件,在用戶上加入文件,然後從瀏覽器磁盤空間下載它。它可以恢復文件,暫停文件等。 (對不起 - 沒有代碼,因爲它會很大,並且包含多種語言(php,js))。

PS:改變你的readfile($path);到:

$handle=fopen($path, 'rb'); 
while (!feof($handle)) 
{ 
    echo fread($handle, 8192); 
    flush(); 
} 
fclose($handle); 

這不加載整個文件到內存中,8KiB的一次只是部分,然後將其發送給用戶。

+0

雖然這是非常真實的 - 這是Apache2的Keep-Alive,這還不夠高。 (再次看到這個問題,我想我會給你一個答案) –

+0

很抱歉,遲到的答案,但保持活着是用於其他原因...大多數服務器將殺死60秒後的PHP - 即使它仍然發送文件(會被殺死)。並且通常不明智地解除限制 – Seti