【PHP-文件下载】遇到的编码格式不正确导致文件下载后乱码、文件大小发生改变的问题
上面说到过文件上传的过程,现在详细说一下文件的下载过程,在下载过程中,曾遇到过下载的文件与原上传文件,大小不一,乱码的情况,现在将详细叙述问题解决的全过程。
先简单说下编码格式,
header("Content-type: text/html; charset=utf-8"); header("Content-type: text/html; charset=gb2312");
这句话的意思是定义PHP页面的编码格式为utf-8或者GB2312,提示浏览器用什么字符集展现,GB还是utf-8,这样才不会造成编码错误而产生乱码。
下载代码实现:文件名为:download.php
<?php header("Content-type:text/html;charset=utf-8"); require_once ("./lib/conn.php"); $id = $_REQUEST["P_ID"]; $sql = "select *from tb_file where id ="{$id}""; $result = mysql_query($sql) or die(mysql_error()); $row = mysql_fetch_array($result); $file_name = urlencode($row[name]);// urlencode对字符串进行编码,urldecode解码字符串//下载文件名 $file_dir = $row[uppath]; //下载文件存放目录 //检查文件是否存在 if (! file_exists ( $file_dir )) { echo "文件找不到"; exit (); } else { $file_dir=iconv("UTF-8","gb2312",$file_dir) ; //将编码转为支持中英文的gb2312编码 if(!isset($file_dir)||trim($file_dir)==""){ return "500服务器内部错误"; } if(!file_exists($file_dir)){ //检查文件是否存在 return "404访问的文件不存在"; } $file_type=explode(".",$file_dir); $file_type=$file_type[count($file_type)-1]; // $file_name=trim($new_name=="")?$file_name; //输入文件标签 header("Content-type: application/octet-stream"); header("Accept-Ranges: bytes"); header("Accept-Length: ".filesize($file_dir)); header("Content-Disposition: attachment; filename=".$file_name); $file_type=fopen($file_dir,"rb"); //打开文件 //输出文件内容 $file_size=filesize($file_dir);//获取文件大小 $buffer=1024; //定义1KB的缓存空间 $file_count=0; //计数器,计算发送了多少数据 while(!feof($file_type) && ($file_size>$file_count)) { //feof检测是否已经到达文件末尾 //如果文件还没读到结尾,且还有数据没有发送 $senddata=fread($file_type,$buffer); //读取文件内容到缓存区 $file_count+=$senddata; echo $senddata; } //echo fread($file_type,filesize($file_url)); fclose($file_type); } ?>
下面简单说下要注意的几个地方。
1.download.php文件设置编码格式为utf-8无BOM的编码方式;
2.当前页面中,所有引进的文件也要设置为utf-8无BOM的编码方式,如:require_once ("./lib/conn.php");conn.php也要设置成utf-8无BOM的编码方式;
符合以上两个条件后,才不会出现下载之后的文件内容中,多出“efbbbf”字符,否则的话,下载的文件大小与原上传的文件大小不一,特别是当上传的文件是****.exe文件的时候,下载之后,根本就打不开,同样,其他的文件流格式的文件,下载之后,用二进制查看,都是在头部多出“efbbbf”字符。
【补充】下载的文件名称是中文的时候,在有的浏览器下是乱码,为解决这一问题,需要利用到一个函数urlencode,就是将字符串进行编码,所以在程序中,有这么一段:
$file_name = urlencode($row[name]);// urlencode对字符串进行编码,urldecode解码字符串//下载文件名
目的就是为了防止下载的时候乱码。
最后附上文件上传时候的主要代码,供大家参考。
$upload=new upload("myFile","test");//实例化 $dest=$upload->uploadFile();//文件上传,返回文件路径upload.class.php代码如下:
<?php class upload{ protected $fileName; protected $maxSize; protected $allowMime; protected $allowExt; protected $uploadPath; protected $imgFlag; protected $fileInfo; protected $error; protected $ext; /** * @param string $fileName * @param string $uploadPath * @param string $imgFlag * @param number $maxSize * @param array $allowExt * @param array $allowMime */ public function __construct($fileName="myFile",
$uploadPath="./uploads",
$imgFlag=true,
$maxSize=5242880,
$allowMime=array("HEX","application/octet-stream","image/jpg","XH"))
{ $this->fileName=$fileName; $this->maxSize=$maxSize; $this->allowMime=$allowMime;//支持的类型 $this->allowExt=$allowExt;//允许的扩展名 $this->uploadPath=$uploadPath; $this->imgFlag=$imgFlag;//检测是否为真实图片 $this->fileInfo=$_FILES[$this->fileName]; } /** * 检测上传文件是否出错 * @return boolean */
protected function checkError(){ if(!is_null($this->fileInfo)){ if($this->fileInfo["error"]>0){ switch($this->fileInfo["error"]){ case 1: $this->error="超过了PHP配置文件中
upload_max_filesize选项的值";
break; case 2: $this->error="超过了表单中MAX_FILE_SIZE设置的值"; break; case 3: $this->error="文件部分被上传"; break; case 4: $this->error="没有选择上传文件"; break; case 6: $this->error="没有找到临时目录"; break; case 7: $this->error="文件不可写"; break; case 8: $this->error="由于PHP的扩展程序中断文件上传"; break; } return false; }else{ return true; } }else{ $this->error="文件上传出错"; return false; } }
/** * 检测上传文件的大小 * @return boolean */
protected function checkSize(){ if($this->fileInfo["size"]>$this->maxSize){ $this->error="上传文件过大"; return false; } return true; } /** * 检测扩展名 * @return boolean */
protected function checkExt(){ $this->ext=pathinfo($this->fileInfo["name"],PATHINFO_EXTENSION); /* if(!in_array($this->ext,$this->allowExt)){ $this->error= "不允许的扩展名!"; return false; } */ return true; } /** * 检测文件的类型 * @return boolean */
protected function checkMime(){ if(!in_array($this->fileInfo["type"],$this->allowMime)){ $this->error="不允许的文件类型!"; return false; } return true; } /** * 检测是否是真实图片 * @return boolean */
protected function checkTrueImg(){ if($this->imgFlag){ if(!@getimagesize($this->fileInfo["tmp_name"])){ $this->error="不是真实图片!"; return false; } return true; } } /** * 检测是否通过HTTP POST方式上传上来的 * @return boolean */
protected function checkHTTPPost(){ if(!is_uploaded_file($this->fileInfo["tmp_name"])){ $this->error="文件不是通过HTTP POST方式上传上来的"; return false; } return true; } /** *显示错误 */
protected function showError(){ exit("<span style="color:red">".$this->error."</span>"); } /** * 检测目录不存在则创建 */
protected function checkUploadPath(){ if(!file_exists($this->uploadPath)){ mkdir($this->uploadPath,0777,true); } } /** * 产生唯一字符串 * @return string */
protected function getUniName(){ //return md5(uniqid(microtime(true),true));
//uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID return uniqid(microtime(true),true);
} /** * 上传文件 * @return string */
public function uploadFile(){ if($this->checkError()&&$this->checkHTTPPost()&&$this->checkExt()){ $this->checkUploadPath(); $this->uniName=$this->getUniName(); $this->destination=$this->uploadPath."/".$this->uniName.".".$this->ext; if(@move_uploaded_file($this->fileInfo["tmp_name"], $this->destination)){ return $this->destination; }else{ $this->error="文件移动失败"; $this->showError(); } }else{ $this->showError(); } } }
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。