2012-11-05 67 views
1


我測試this code下載10 MB塊大文件:當下載帶有「FWRITE」二進制文件 - 「0D」字節消失

/** 
* Copy remote file over HTTP one small chunk at a time. 
* 
* @param $infile The full URL to the remote file 
* @param $outfile The path where to save the file 
*/ 
function copyfile_chunked($infile, $outfile) { 
    $chunksize = 10 * (1024 * 1024); // 10 Megs 

    /** 
    * parse_url breaks a part a URL into it's parts, i.e. host, path, 
    * query string, etc. 
    */ 
    $parts = parse_url($infile); 
    $i_handle = fsockopen($parts['host'], 80, $errstr, $errcode, 5); 
    $o_handle = fopen($outfile, 'wb'); 

    if ($i_handle == false || $o_handle == false) { 
     return false; 
    } 

    if (!empty($parts['query'])) { 
     $parts['path'] .= '?' . $parts['query']; 
    } 

    /** 
    * Send the request to the server for the file 
    */ 
    $request = "GET {$parts['path']} HTTP/1.1\r\n"; 
    $request .= "Host: {$parts['host']}\r\n"; 
    $request .= "User-Agent: Mozilla/5.0\r\n"; 
    $request .= "Keep-Alive: 115\r\n"; 
    $request .= "Connection: keep-alive\r\n\r\n"; 
    fwrite($i_handle, $request); 

    /** 
    * Now read the headers from the remote server. We'll need 
    * to get the content length. 
    */ 
    $headers = array(); 
    while(!feof($i_handle)) { 
     $line = fgets($i_handle); 
     if ($line == "\r\n") break; 
     $headers[] = $line; 
    } 

    /** 
    * Look for the Content-Length header, and get the size 
    * of the remote file. 
    */ 
    $length = 0; 
    foreach($headers as $header) { 
     if (stripos($header, 'Content-Length:') === 0) { 
      $length = (int)str_replace('Content-Length: ', '', $header); 
      break; 
     } 
    } 

    /** 
    * Start reading in the remote file, and writing it to the 
    * local file one chunk at a time. 
    */ 
    $cnt = 0; 
    while(!feof($i_handle)) { 
     $buf = ''; 
     $buf = fread($i_handle, $chunksize); 
     $bytes = fwrite($o_handle, $buf); 
     if ($bytes == false) { 
      return false; 
     } 
     $cnt += $bytes; 

     /** 
     * We're done reading when we've reached the conent length 
     */ 
     if ($cnt >= $length) break; 
    } 

    fclose($i_handle); 
    fclose($o_handle); 
    return $cnt; 
} 

我第一次一個小圖像上測試該代碼。圖像被下載到我的帳戶,但以一種破損的形式:所有的字節看起來是正確的,從下載的圖像中刪除「0D」字節,這使得它不可用。
爲什麼會發生這種情況,我該如何克服它?
謝謝!

+0

您最終讀取的字節數與「Content-Length」指示的一樣多嗎? – Jon

+0

嗨,喬恩。奇怪的事情。原始圖像是15444字節,該函數返回15444字節被下載,但是當我檢索下載的圖像時,它證明只有15397字節,可能是因爲缺少「0D」字節。 – GreenBear

+0

是否有一個特別的原因,你不使用一個工作的http客戶端庫?你古怪的頭解碼不符合HTTP。並非所有的答案都來自於分塊的TE。 – mario

回答

1

美好的一天大家,謝謝你的幫助。
現在問題已解決,罪魁禍首已確定。
我一直在看一些書,發現這個:
ftp_get()將遠程服務器上的文件複製到您的計算機上。 FTP_ASCII參數將文件轉換爲ASCII文本。在此選項下,當您從一個操作系統移動到另一個操作系統時,換行符結尾爲 。另一個選項 是FTP_BINARY,它用於非文本文件,因此不會發生換行轉換。
在我的問題中提供的代碼工作正常,並正確下載圖像。
當我檢查圖像時,我正在使用由php託管供應商提供的php文件管理器將它下載到我的電腦。顯然,誰不擅長PHP,因爲他們使用上面提到的FTP_ASCII參數來傳輸二進制文件。因此圖像被損壞。
當我直接從FTP帳戶下載圖像時,圖像證明與原始圖像相同。
因此,最終,問題出在PHP代碼上,而不是我編譯的代碼。