2013-06-28 53 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