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 相关文章推荐
Get或Post提交值的非法数据处理
Oct 09 PHP
php5.2时间相差8小时
Jan 15 PHP
用PHP制作的意见反馈表源码
Mar 11 PHP
php读取xml实例代码
Jan 28 PHP
php 将字符串按大写字母分隔成字符串数组
Apr 30 PHP
PHP中使用CURL伪造来路抓取页面或文件
May 04 PHP
防止本地用户用fsockopen DDOS攻击对策
Nov 02 PHP
仿Aspnetpager的一个PHP分页类代码 附源码下载
Oct 08 PHP
PHP+APACHE实现网址伪静态
Feb 22 PHP
CI框架文件上传类及图像处理类用法分析
May 18 PHP
Yii2中datetime类的使用
Dec 17 PHP
PHPTree――php快速生成无限级分类
Mar 30 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
PHP三元运算符的结合性介绍
2012/01/10 PHP
php empty()与isset()区别的详细介绍
2013/06/17 PHP
jQuery隔行变色与普通JS写法的对比
2013/04/21 Javascript
jQuery中filter()和find()的区别深入了解
2013/09/25 Javascript
html文件中jquery与velocity变量中的$冲突的解决方法
2013/11/01 Javascript
window.open()详解及浏览器兼容性问题示例探讨
2014/05/29 Javascript
使用Node.js实现一个简单的FastCGI服务器实例
2014/06/09 Javascript
jQuery常用操作方法及常用函数总结
2014/06/19 Javascript
完美兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面js代码
2014/12/17 Javascript
JS 对象(Object)和字符串(String)互转方法
2016/05/20 Javascript
基于jQuery实现歌词滚动版音乐播放器的代码
2016/09/17 Javascript
jQuery初级教程之网站品牌列表效果
2017/08/02 jQuery
深入掌握 react的 setState的工作机制
2017/09/27 Javascript
微信小程序日期时间选择器使用方法
2018/02/01 Javascript
Vue2.0学习系列之项目上线的方法步骤(图文)
2018/09/25 Javascript
JavaScript常见事件处理程序实例总结
2019/01/05 Javascript
使用 js 简单的实现 bind、call 、aplly代码实例
2019/09/07 Javascript
浅谈vuex为什么不建议在action中修改state
2020/02/02 Javascript
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
JS绘图Flot如何实现可选显示曲线图功能
2020/10/16 Javascript
python使用calendar输出指定年份全年日历的方法
2015/04/04 Python
简要讲解Python编程中线程的创建与锁的使用
2016/02/28 Python
Python实现输出程序执行进度百分比的方法
2017/09/16 Python
Python闭包执行时值的传递方式实例分析
2018/06/04 Python
Django 通过JS实现ajax过程详解
2019/07/30 Python
python+django+selenium搭建简易自动化测试
2020/08/19 Python
python 利用opencv实现图像网络传输
2020/11/12 Python
Ruby如何创建一个线程
2013/03/10 面试题
中国梦主题教育活动总结
2014/05/05 职场文书
经典禁毒标语
2014/06/16 职场文书
高中学生自我评价范文
2014/09/23 职场文书
科学发展观标语
2014/10/08 职场文书
党的群众路线教育实践活动调研报告
2014/11/03 职场文书
QT连接MYSQL数据库的详细步骤
2021/07/07 MySQL
Go语言基础切片的创建及初始化示例详解
2021/11/17 Golang
python多次执行绘制条形图
2022/04/20 Python