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 多维数组的排序问题 根据二维数组中某个项排序
Nov 09 PHP
DISCUZ在win2003环境下 Unable to access ./include/common.inc.php in... 的问题终极解决方案
Nov 21 PHP
解析使用ThinkPHP应该掌握的调试手段
Jun 20 PHP
PHP输出缓存ob系列函数详解
Mar 11 PHP
php switch语句多个值匹配同一代码块应用示例
Jul 29 PHP
Laravel实现用户注册和登录
Jan 23 PHP
php视频拍照上传头像功能实现代码分享
Oct 08 PHP
PHP文件上传操作实例详解
Sep 27 PHP
php用户密码加密算法分析【Discuz加密算法】
Oct 12 PHP
PHP中quotemeta()函数的用法讲解
Apr 04 PHP
laravel 框架结合关联查询 when()用法分析
Nov 22 PHP
聊聊 PHP 8 新特性 Attributes
Aug 19 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生成二维码图片方法汇总
2016/12/17 PHP
根据分辩率调用不同的CSS.
2007/01/08 Javascript
jQuery UI Datepicker length为空或不是对象错误的解决方法
2010/12/19 Javascript
JAVASCRIPT函数作用域和提前声明 分享
2013/08/22 Javascript
javascript在myeclipse中报错的解决方法
2013/10/29 Javascript
js jq 单击和双击区分示例介绍
2013/11/05 Javascript
jquery进行数组遍历如何跳出当前的each循环
2014/06/05 Javascript
JavaScript中实现Map的示例代码
2015/09/09 Javascript
jQuery实用技巧必备(下)
2015/11/03 Javascript
深入理解jquery中的事件与动画
2016/05/24 Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
2016/08/01 Javascript
Vue.js 和 MVVM 的注意事项
2016/11/07 Javascript
Vue实现双向绑定的方法
2016/12/22 Javascript
纯js实现页面返回顶部的动画(超简单)
2017/08/10 Javascript
vue引入新版 vue-awesome-swiper插件填坑问题
2018/01/25 Javascript
详解angular路由高亮之RouterLinkActive
2018/04/28 Javascript
nodejs aes 加解密实例
2018/10/10 NodeJs
微信小程序显示倒计时功能示例【测试可用】
2018/12/03 Javascript
基于Vue SEO的四种方案(小结)
2019/07/01 Javascript
[44:01]2018DOTA2亚洲邀请赛3月30日 小组赛B组 EG VS paiN
2018/03/31 DOTA
通过python下载FTP上的文件夹的实现代码
2013/02/10 Python
python抓取网页中的图片示例
2014/02/28 Python
Python常用列表数据结构小结
2014/08/06 Python
使用Python从有道词典网页获取单词翻译
2016/07/03 Python
教你用Python脚本快速为iOS10生成图标和截屏
2016/09/22 Python
python实现AES加密解密
2019/03/28 Python
以SQLite和PySqlite为例来学习Python DB API
2020/02/05 Python
python GUI库图形界面开发之PyQt5窗口控件QWidget详细使用方法
2020/02/26 Python
mac在matplotlib中显示中文的操作方法
2020/03/06 Python
Python小整数对象池和字符串intern实例解析
2020/03/21 Python
查看keras各种网络结构各层的名字方式
2020/06/11 Python
Johnson Fitness澳大利亚:高级健身器材
2021/03/16 全球购物
研究生求职推荐信范文
2013/11/30 职场文书
《只有一个地球》教学反思
2014/02/14 职场文书
会议邀请函
2015/01/30 职场文书
安全生产奖惩制度
2015/08/06 职场文书