【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();
		}
	}
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值