2012-04-13 288 views
4

我有一个很奇怪的问题,我的下载脚本为什么我下载的文件一直损坏或损坏?

它基本上

1.gets文件ID以“GET”方法

2.gets从该文件的名称和位置数据库

它3.sends与报头中的客户端和READFILE

但ST RANGELY该文件永远是为破坏或损坏

一样,如果它是一个zip或rar文件 文件大小是正确的,它打开OK

,但我不能打开它内部的压缩文件,这时候我得到的文件损坏错误

这是怪异的Cuz如果代码有一个问题,我不应该甚至能够打开压缩文件(或至少我觉得我应该不会)

另一件事是我在发送标题之前打印出文件的路径,以确保一切正常

我已经把文件地址的网址并下载文件,文件是确定没有错误

所以一切发送头

这里是我的代码之前是好的

 $file_id = isset($_GET['id']) && (int)$_GET['id'] != 0 ? (int)$_GET['id'] : exit; 


     //////// finging file info 
     $file = comon::get_all_by_condition('files' , 'id' , $file_id); 
     if(!$file) exit; 
     foreach($file as $file){ 
     $location = $file['location']; 
     $filename = $file['file_name']; 
     } 
     ///////////// 


     $site = comon::get_site_domian(); 

     $ext = trim(end(explode('.' , $filename))); 
     $abslout_path = 'http://'.$site.'/'.$location.'/'.$filename; 
     $relative = $location.'/'.$filename; 



    ////////////////// content type 
      switch($ext) { 
      case 'txt': 
       $cType = 'text/plain'; 
      break;    
      case 'pdf': 
       $cType = 'application/pdf'; 
      break; 

      case 'zip': 
       $cType = 'application/zip'; 
      break; 

      case 'doc': 
       $cType = 'application/msword'; 
      break; 

      case 'xls': 
       $cType = 'application/vnd.ms-excel'; 
      break; 

      case 'ppt': 
       $cType = 'application/vnd.ms-powerpoint'; 
      break; 
      case 'gif': 
       $cType = 'image/gif'; 
      break; 
      case 'png': 
       $cType = 'image/png'; 
      break; 
      case 'jpeg': 
      case 'jpg': 
       $cType = 'image/jpg'; 
      break; 

      default: 
       $cType = 'application/force-download'; 
      break; 
     } 
    //////////////// just checking 

    if(!file_exists($relative)){ 
     echo $relative; 
     echo '<br />'; 
     exit; 
     } 

    if(!is_readable($relative)) 
    exit('its not redable'); 



    if(headers_sent()) 
    exit('headers ? already sent !! '); 



    header('Pragma: public'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Cache-Control: private', false); // required for certain browsers 
    header('Content-Description:File Transfer'); 
    header($_SERVER['SERVER_PROTOCOL'].' 200 OK'); 
    header('Content-Type:'.$cType); 
    header('Content-Disposition: attachment; filename="'. basename($filename) . '";'); 
    header('Content-Transfer-Encoding: binary'); 
    header('Content-Length: ' . filesize($relative)); 
    readfile($abslout_path); 
    exit; 

我已经检查了标题几次,他们都很好(我认为),我也添加了所有人知道的标题只是为了确保!

我开始觉得它可能不是脚本 ,比如char编码或文件夹权限!或类似的东西 !!

我错过了什么?

回答

7

这似乎只是强制下载代码的分配,这里是一个很好的函数,我使用所有的时间。它也会处理超过2GB的文件。

<?php 
$file_id = (isset($_GET['id']) && (int)$_GET['id'] != 0) ? (int)$_GET['id'] : exit; 

/*finding file info*/ 
$file = comon::get_all_by_condition('files', 'id', $file_id); 
$path = $file['location'] . '/' . $file['file_name']; 

if (!is_file($path)) { 
    echo 'File not found.('.$path.')'; 
} elseif (is_dir($path)) { 
    echo 'Cannot download folder.'; 
} else { 
    send_download($path); 
} 

return; 

//The function with example headers 
function send_download($file) { 
    $basename = basename($file); 
    $length = sprintf("%u", filesize($file)); 

    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename="' . $basename . '"'); 
    header('Content-Transfer-Encoding: binary'); 
    header('Connection: Keep-Alive'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Pragma: public'); 
    header('Content-Length: ' . $length); 

    set_time_limit(0); 
    readfile($file); 
} 
?> 
+0

后视图thanx伟大的工作 – max 2012-04-13 17:51:35

+0

@DanBray多么可怕的编辑,批评社区的耻辱 – 2016-03-10 18:19:26

+0

@LawrenceCherone使代码工作如此糟糕?代码有一个'''缺少''。你认为把代码与错别字放在一起会更好吗?缺少的'''可能会混淆人并浪费大量时间。 – 2016-03-10 18:22:48

2

您可以使用脚本包含通知或警告,请尝试禁用你的脚本的顶部报告错误:

error_reporting(0); 
2

非常好,乐于助人也...

,但有一个问题你的代码 -

header('Content-Disposition: attachment; 
filename="'.basename($file).'"'; 

请与本以下更改 -

header('Content-Disposition: attachment; 
filename="'.basename($file).'"'); 

你忘了关闭它。

2
if (file_exists($file)) { 
set_time_limit(0); 
     header('Connection: Keep-Alive'); 
    header('Content-Description: File Transfer'); 
      header('Content-Type: application/octet-stream'); 
      header('Content-Disposition: attachment; filename="'.basename($file).'"'); 
      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($file)); 
      ob_clean(); 
      flush(); 
      readfile($file); 


} 
+0

这对我来说非常完美。下载的文件没有损坏。我用劳伦斯Cherone建议的PHP脚本,但下载的文件仍然腐败。感谢Altair CA.并感谢所有。 – 2017-05-12 13:37:50

0

确保你没有在最后一行后执行任何代码readfile(FILE_NAME)

我不得不添加die();exit();的最后一行,因为MVC框架继续呈现readfile