2012-11-05 37 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代码上,而不是我编译的代码。