PHP讀取圖片,讀取到的字節比圖片實際字節多了,仔細研讀了PHP手冊自認為代碼沒問題


我的Code如下:
<?php
 
  $filepath="c:\123.jpg";
  $filesize=filesize($filepath);
  $fs=fopen($filepath,"r");
  $readlen=1024;//每次讀取多少字節
  $rlen=0;//共讀取多少字節
  while(!feof($fs)){
     $data=fread($fs,$readlen);
     $rlen+=$readlen;
   }
   fclose($fs);
   echo '文件大小'.$filesize.'<br/>';
   echo '讀取大小'.$rlen.'<br/>';
?>

PHP朋友們給看看,我電腦系統windows 7的,這應該與系統無關系.

10 个解决方案

#1


這恰恰與系統有關!
window 的文件打開方式有文本方式和二進制方式的區別
文本方式下,會對每個 \n (不是 \r\n 組合)附加一個 \r,形成 \r\n
所以字節數就多出來了

你需要用二進制防止打開圖片
$fs=fopen($filepath,"r b");

或者直接用 file_get_contents

#2


還是沒讀仔細,手冊這樣寫:
---------------------------------------------------------

Note: 

不同的操作系統家族具有不同的行結束習慣。當寫入一個文本文件並想插入一個新行時,需要使用符合操作系統的行結束符號。基於 Unix 的系統使用 \n作為行結束字符,基於 Windows 的系統使用 \r\n作為行結束字符,基於 Macintosh 的系統使用 \r作為行結束字符。 

如果寫入文件時使用了錯誤的行結束符號,則其它應用程序打開這些文件時可能會表現得很怪異。 

Windows 下提供了一個文本轉換標記('t')可以透明地將 \n 轉換為 \r\n。與此對應還可以使用 'b' 來強制使用二進制模式,這樣就不會轉換數據。要使用這些標記,要么用 'b' 或者用 't' 作為 mode 參數的最后一個字符。 

默認的轉換模式依賴於 SAPI 和所使用的 PHP 版本,因此為了便於移植鼓勵總是指定恰當的標記。如果是操作純文本文件並在腳本中使用了 \n 作為行結束符,但還要期望這些文件可以被其它應用程序例如 Notepad 讀取,則在 mode 中使用 't'。在所有其它情況下使用 'b'。 

在操作二進制文件時如果沒有指定 'b'標記,可能會碰到一些奇怪的問題,包括壞掉的圖片文件以及關於 \r\n 字符的奇怪問題。 



Note: 

為移植性考慮,強烈建議在用 fopen()打開文件時總是使用 'b' 標記。 



Note: 

再一次,為移植性考慮,強烈建議你重寫那些依賴於 't' 模式的代碼使其使用正確的行結束符並改成 'b' 模式。
---------------------------------------------------------------------------------------------

1.不管什么語言,非文本文件習慣一下用rb好
2.php的話,win系統就一律習慣b,尤其是unicode文本不使用b參數很容易出錯

#3


還是有問題,
$fs=fopen($filepath,"rb"); 
比實際文件字節多讀出了十幾個字節
是while循環讀取有問題?
有在自己機器上成功得出正確結果的朋友嗎?

#4


引用 3 樓 vs2008ASPNET 的回復:
還是有問題,
$fs=fopen($filepath,"rb"); 
比實際文件字節多讀出了十幾個字節
是while循環讀取有問題?
有在自己機器上成功得出正確結果的朋友嗎?


while沒問題啊

#5


$rlen+=$readlen;
改為
$rlen += strlen($data);

通常最后一次讀取時,是讀不到 $readlen 字節的。因為文件已結束


#6


我本意是實現讀取服務器一個圖片文件,發送到客戶端
修改后的完整代碼是,但仍舊有問題
<?php
 
  function DownFile_shortpath($filename,$downname){
   $filepath=str_ireplace("/","\\",$_SERVER['DOCUMENT_ROOT'].$filename);
   $filepath=iconv("utf-8","gb2312",$filepath);
   $downname=iconv("utf-8","gb2312",$downname);
   if(!file_exists($filepath)){
    throw new Exception('文件不存在');
   }
   //$count=0;
   //添加http報文
   header("Content-type: application/octet-stream");
   header("Accept-Ranges: bytes");
   header("Accept-Length: $filesize");
   header("Content-Disposition: attachment; filename=".$downname);
   $filesize=filesize($filepath);
   $fs=fopen($filepath,"rb");
   $readlen=1024;
   while(!feof($fs)){
    $data=fread($fs,$readlen);
    echo $data;
   }
   fclose($fs);
  }
 DownFile_shortpath('\http\123.jpg','123.jpg');
?>

#7


引用 5 樓 xuzuning 的回復:
$rlen+=$readlen;
改為
$rlen += strlen($data);

通常最后一次讀取時,是讀不到 $readlen 字節的。因為文件已結束


給個QQ吧,請教一下你

#8


此代碼在windows xp上成功運行 windows 7上仍舊有問題
<?php
 $filepath="f:\\C.rar";
 $downname="測試.rar";
 $filepath=iconv("utf-8","gb2312",$filepath); 
 $downname=iconv("utf-8","gb2312",$downname); 
 $filesize=filesize($filepath); 
 header("Content-type: application/octet-stream");    
 header("Accept-Ranges: bytes");    
 header("Accept-Length: $filesize");    
 header("Content-Disposition: attachment; filename=".$downname); 
 $fs=fopen($filepath,"rb");   
 $readlen=1024;
 while(!feof($fs)){  
$data=fread($fs,$readlen); 
echo $data;
 }    
 fclose($fs); 

?>

#9


你還要考慮最后一塊不足1024的情況

while(!feof($fs) && $file_size - 已讀完的字節 > $readlen)

退出循環再輸出剩余字節

#10


學習了,謝謝!

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com