php实现支持中文的文件下载功能示例


Posted in PHP onAugust 30, 2017

前言

本文主要给大家介绍了关于php实现支持中文的文件下载功能的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

问题说明

文件下载,通常有一种最为简单的方法,那就是将url直接指向服务器上文件的所在位置。但是这个方法存在很大的安全隐患。

  • 暴露了服务器文件目录结构
  • 无法禁止非法请求来源,无法对文件下载请求做安全验证

解决方案

一、将文件下载请求映射到后端程序url

借助http服务器(apache/nginx)实现映射功能

这里以apache为例进行说明

借助apache的rewrite模块,配置rewrite规则。(关于如何开启rewrite模块,网上很多资源,这里不再赘诉)
在项目根目录下创建.htaccess文件,写入rewrite规则

RewriteEngine on
#将所有以rar/zip结尾的url,映射给download.php文件
RewriteRule (.*\.(rar|zip))$ download.php?file=$1 [NC]

将所有以rar/zip结尾的url,映射给download.php文件(这里为了方便直接映射到了一个php脚本中,如果是使用框架,那就映射到具体的控制器中的某个方法!例如:index.php?c=home&a=download)

二、编写具体的文件下载逻辑

项目目录

以本地项目为例,用户需要下载的zip文件,放在当前项目的temp目录下

php实现支持中文的文件下载功能示例

示例

直接上代码,代码中有详细注释

<?php
//接收需要下载的文件名称
if(!isset($_GET['file'])) exit('Filename is empty');
if(empty($_GET['file'])) exit('Filename not valid');
ob_clean();//清除一下缓冲区
//获得文件名称
$filename = basename(urldecode($_GET['file']));
//文件完整路径(这里将真实的文件存放在temp目录下)
$filePath = __DIR__."/temp/".$filename;
//将utf8编码转换成gbk编码,否则,文件中文名称的文件无法打开
$filePath = iconv('UTF-8','gbk',$filePath);
//检查文件是否可读
if(!is_file($filePath) || !is_readable($filePath)) exit('Can not access file '.$filename);
/**
 * 这里应该加上安全验证之类的代码,例如:检测请求来源、验证UA标识等等
 */
//以只读方式打开文件,并强制使用二进制模式
$fileHandle=fopen($filePath,"rb");
if($fileHandle===false){
  exit("Can not open file: $filename");
}
//文件类型是二进制流。设置为utf8编码(支持中文文件名称)
header('Content-type:application/octet-stream; charset=utf-8');
header("Content-Transfer-Encoding: binary");
header("Accept-Ranges: bytes");
//文件大小
header("Content-Length: ".filesize($filePath));
//触发浏览器文件下载功能
header('Content-Disposition:attachment;filename="'.urlencode($filename).'"');
//循环读取文件内容,并输出
while(!feof($fileHandle)) {
  //从文件指针 handle 读取最多 length 个字节(每次输出10k)
  echo fread($fileHandle, 10240);
}
//关闭文件流
fclose($fileHandle);

这里只是做了一个示例(只包括核心功能),为了方便说明直接以GET方式从url中获取用户想要下载的文件名称

注意以下两行代码(为了能够下载中文名称的文件)

$filePath = iconv('UTF-8','gbk',$filePath);
header('Content-type:application/octet-stream; charset=utf-8');

如果用户需要下载的是中文名称的文件。则需要将文件路径转换成gbk编码,否则会出现 文件不存在 之类的错误。header中设置utf8编码,也是同样的道理

下载文件

打开浏览器,访问 http://127.0.0.1/rewrite/尴尬.zip 文件便开始下载了

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
php 无限级分类学习参考之对ecshop无限级分类的解析 带详细注释
Mar 23 PHP
mysqli_set_charset和SET NAMES使用抉择及优劣分析
Jan 13 PHP
PHP实现的封装验证码类详解
Jun 18 PHP
php使用pdo连接报错Connection failed SQLSTATE的解决方法
Dec 15 PHP
php给每个段落添加空格的方法
Mar 20 PHP
php分割合并两个字符串的函数实例
Jun 19 PHP
PHP技术开发微信公众平台
Jul 22 PHP
PHP中利用sleep函数实现定时执行功能实现代码
Aug 25 PHP
自制PHP框架之设计模式
May 07 PHP
详谈symfony window下的安装 安装时候出现的问题以及解决方法
Sep 28 PHP
PHP迭代器和迭代的实现与使用方法分析
Apr 19 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
Mar 29 PHP
利用PHPStorm如何开发Laravel应用详解
Aug 30 #PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
Aug 29 #PHP
PHP单例模式与工厂模式详解
Aug 29 #PHP
PHP迭代与递归实现无限级分类
Aug 28 #PHP
yii2中LinkPager增加总页数和总记录数的实例
Aug 28 #PHP
PHP大文件分割上传 PHP分片上传
Aug 28 #PHP
thinkphp ajaxfileupload实现异步上传图片的示例
Aug 28 #PHP
You might like
咖啡冲泡指南 咖啡有哪些制作方式 单品咖啡 意式咖啡
2021/03/06 冲泡冲煮
php5编程中的异常处理详细方法介绍
2008/07/29 PHP
JS与PHP向函数传递可变参数的区别实例代码
2011/05/18 PHP
PHP include任意文件或URL介绍
2014/04/29 PHP
PHP临时文件的安全性分析
2014/07/04 PHP
PHP数据分析引擎计算余弦相似度算法示例
2017/08/08 PHP
js的逻辑运算符 ||
2010/05/31 Javascript
细说浏览器特性检测(2)-通用事件检测
2010/11/05 Javascript
js中判断Object、Array、Function等引用类型对象是否相等
2012/08/29 Javascript
关于JavaScript中的关联数组分析
2013/04/09 Javascript
A标签中通过href和onclick传递的this对象实现思路
2013/04/19 Javascript
基于jQuery创建鼠标悬停效果的方法
2015/03/07 Javascript
javascript实现淡蓝色的鼠标拖动选择框实例
2015/05/09 Javascript
JQuery悬停控制图片轮播——代码简单
2015/08/05 Javascript
JavaScript函数的调用以及参数传递
2015/10/21 Javascript
bootstrap快速制作后台界面
2016/12/05 Javascript
JavaScript实现大图轮播效果
2017/01/11 Javascript
如何从零开始利用js手写一个Promise库详解
2018/04/19 Javascript
VUE 3D轮播图封装实现方法
2018/07/03 Javascript
vue3.0 CLI - 2.3 - 组件 home.vue 中学习指令和绑定
2018/09/14 Javascript
ES6 迭代器与可迭代对象的实现
2019/02/11 Javascript
vue 在单页面应用里使用二级套嵌路由
2020/12/19 Vue.js
python中使用xlrd、xlwt操作excel表格详解
2015/01/29 Python
分析在Python中何种情况下需要使用断言
2015/04/01 Python
wxpython中自定义事件的实现与使用方法分析
2016/07/21 Python
Python机器学习之SVM支持向量机
2017/12/27 Python
利用Pandas和Numpy按时间戳将数据以Groupby方式分组
2019/07/22 Python
python 解决flask uwsgi 获取不到全局变量的问题
2019/12/22 Python
opencv 实现特定颜色线条提取与定位操作
2020/06/02 Python
HTML5超文本标记语言的实现方法
2020/09/24 HTML / CSS
德国购买门票网站:ADticket.de
2019/10/31 全球购物
迪卡侬中国官网:Decathlon中国
2020/08/10 全球购物
利达恒信公司.NET笔试题面试题
2016/03/05 面试题
《卖木雕的少年》教学反思
2014/04/11 职场文书
大学生党员个人总结
2015/02/13 职场文书
为Java项目添加Redis缓存的方法
2021/05/18 Redis