2011-11-05 58 views
1

我有一個腳本從服務器上下載文件,所有的作品都很好。但是,當文件被下載時,它是一個JPG或PNG文件。我似乎無法用任何程序打開它來查看它。 (Windows照片庫或煙花)使用fopen(),fread(),feof()下載文件...下載的文件被破壞

當我下載一個視頻文件(AVI)。我無法用windows媒體播放器打開它,但我可以用vlc媒體播放器打開它。

我總是收到錯誤消息,不能讀取文件或文件損壞。

這裏是代碼,它是可靠的,或者我應該考慮使用fsocketopen或curl也許。

我試過改變標題尋找更多的答案在網絡上,沒有運氣。

任何人有一個想法是什麼錯?

chmod("extensions_img/test.jpg",0755); 

$fullPath = "http://www.website_url.com/extensions_img/test.jpg"; 

if ($fd = fopen ($fullPath, "r")) { 

    $fsize = filesize("extensions_img/test.jpg"); 

    $path_parts = pathinfo($fullPath); 
    $ext = strtolower($path_parts["extension"]); 

    switch($ext) { 

     case "pdf": 
      $ctype = "application/pdf"; 
      break; 
     case "exe": 
      $ctype = "application/octet-stream"; 
      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": 
      $ctype = "image/jpg"; 
      break; 
     case "jpg": 
      $ctype = "image/jpg"; 
      break; 
     case "mp3": 
      $ctype = "audio/mp3"; 
      break; 
     case "wav": 
      $ctype = "audio/x-wav"; 
      break; 
     case "wma": 
      $ctype = "audio/x-wav"; 
      break; 
     case "mpeg": 
      $ctype = "video/mpeg"; 
      break; 
     case "mpg": 
      $ctype = "video/mpeg"; 
      break; 
     case "mpe": 
      $ctype = "video/mpeg"; 
      break; 
     case "mov": 
      $ctype = "video/quicktime"; 
      break; 
     case "avi": 
      $ctype = "video/x-msvideo"; 
      break; 
     case "src": 
      $ctype = "plain/text"; 
      break; 
     default: 
      $ctype = "application/force-download"; 
    } 

    header("Pragma: public"); 

    header("Expires: 0"); 

    header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 

    header("Cache-Control: private",false); 

    header("Content-type: " . $ctype); 

    header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); 

    header("Content-Transfer-Encoding: binary"); 

    header("Content-length: $fsize"); 
    header("Cache-control: public"); //use this to open files directly 

    while(!feof($fd)) { 
     $buffer = fread($fd, 4096); 
    flush(); 
    } 
} 
fclose ($fd); 
+0

試着用文本文件做它,然後看文件的內容。這可能是因爲有PHP輸出到緩衝區的錯誤消息,所以他們在垃圾文件。 – prodigitalson

+0

'$ fsize'總是'0',因爲文件不存在。 – KingCrunch

回答

1

嘗試:

while(!feof($fd)) { 
    echo fread($fd, 4096); 
    flush(); 
} 

你沒有任何呼應可能使你的文件是空的?

+1

爲什麼減號? – samura

+0

thx samura完全解決了這個問題=)...我試着使用while(!feof($ fd)){ $ buffer = fread($ fd,4096); \t \t echo $ buffer; \t \t flush(); }但是你的方法...... LIFESAVER一直在處理這個問題。 thx ....和btw donno什麼發生在零下1,也許我acc。打了它的手。 –

0

您正在發送Content-length:標題,其中包含您錯誤獲取的文件大小。

// You are opening a remote file: 
$fullPath = "http://www.website_url.com/extensions_img/test.jpg"; 

// You are retrieving the filesize of a local file that may or may not exist 
$fsize = filesize("extensions_img/test.jpg"); 

所以,最有可能的,你真的Content-length如下所示:

header("Content-length: 0"); 

...除非你有相同名稱的實際本地文件,那麼您會發現其提供文件大小而不是預期的遠程文件。

根據filesize() documentation,支持一些URL包裝器。您可以嘗試從遠程文件中檢索文件大小:

從PHP 5.0.0開始,此函數也可用於某些URL包裝器。請參閱支持的協議和包裝以確定哪些包裝支持stat()系列功能。

$fsize = filesize($fullpath); 
+0

感謝您的快速回復。我最初設置$ fsize = filesize($ fullpath);但它會拋出以下錯誤(Warning:filesize():stat失敗,因爲http://www.website_url/extensions_img/test.jpg)。但如果我保留$ fsize = filesize(「extensions_img/test.jpg」);我注意到文件的全部大小被下載。 –

+0

@MortenHøgseth如果你無法通過http獲取文件大小,我相信你必須下載文件並保存到本地,然後才能將其傳輸到客戶端。如果你只是省略了Content-length頭部,它會起作用嗎? –

+0

您可能可以使用cURL從提供服務器的服務器獲取內容長度。 –

0

使用filesize($url)將下載文件兩次。而且不知道爲什麼你正在使用fopen/fread無論如何,當有file_get_contentsfpassthru

$data = file_get_contents($url); 
$size = strlen($data); 
$mime = current(preg_grep('/^Content-Type:/i', $http_response_header)); 

請注意如何,這也讓你正確的MIME類型(只是沿着整個stirng通過header通過爲簡單起見)。甚至所有的標題。

+0

thx的回覆,我會讀取file_get_contents和fpassthru函數。 –

+0

在這種情況下,file_get_contents不是一個好主意,a)它會將整個文件讀入內存,並且b)用戶無法開始下載文件,直到服務器讀入整個文件(內存效率低下且速度慢) – StackOverflowed