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 相关文章推荐
一个简单计数器的源代码
Oct 09 PHP
介绍几个array库的新函数 php
Dec 29 PHP
将数组写入txt文件 var_export
Apr 21 PHP
php重定向的三种方法分享
Feb 22 PHP
php引用返回与取消引用的详解
Jun 08 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
Feb 18 PHP
ThinkPHP模版引擎之变量输出详解
Dec 05 PHP
php实现微信公众平台账号自定义菜单类
Oct 11 PHP
PHP通过反射动态加载第三方类和获得类源码的实例
Nov 27 PHP
PHP十六进制颜色随机生成器功能示例
Jul 24 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
Jun 16 PHP
让Laravel API永远返回JSON格式响应的方法示例
Sep 05 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字符串的比较函数strcmp()与strcasecmp()的使用详解
2013/05/15 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
ThinkPHP控制器详解
2015/07/27 PHP
PHP输入流php://input实例讲解
2015/12/22 PHP
yii2 modal弹窗之ActiveForm ajax表单异步验证
2016/06/13 PHP
jquery 上下滚动广告
2009/06/17 Javascript
关于jQuery中的end()使用方法
2011/07/10 Javascript
在JavaScript里嵌入大量字符串常量的实现方法
2013/07/07 Javascript
JavaScript中setUTCFullYear()方法的使用简介
2015/06/12 Javascript
jQuery获取页面及个元素高度、宽度的总结——超实用
2015/07/28 Javascript
基于jquery实现全屏滚动效果
2015/11/26 Javascript
Node.js重新刷新session过期时间的方法
2016/02/04 Javascript
jQuery实现模拟flash头像裁切上传功能示例
2016/12/11 Javascript
js实现图片上传预览原理分析
2017/07/13 Javascript
基于cropper.js封装vue实现在线图片裁剪组件功能
2018/03/01 Javascript
vue better scroll 无法滚动的解决方法
2018/06/07 Javascript
解决vue-cli项目打包出现空白页和路径错误的问题
2018/09/04 Javascript
react-navigation之动态修改title的内容
2018/09/26 Javascript
Nginx设置为Node.js的前端服务器方法总结
2019/03/27 Javascript
js实现简单页面全屏
2019/09/17 Javascript
Python中的yield浅析
2014/06/16 Python
python下os模块强大的重命名方法renames详解
2017/03/07 Python
Python操作redis实例小结【String、Hash、List、Set等】
2019/05/16 Python
django 配置阿里云OSS存储media文件的例子
2019/08/20 Python
Python局部变量与全局变量区别原理解析
2020/07/14 Python
基于python的opencv图像处理实现对斑马线的检测示例
2020/11/29 Python
Python 调用C++封装的进一步探索交流
2021/03/04 Python
详解CSS3媒体查询响应式布局bootstrap 框架原理实战(推荐)
2020/11/16 HTML / CSS
澳大利亚窗帘商店:Curtain Wonderland
2019/12/01 全球购物
在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排
2014/01/13 面试题
分公司负责人任命书
2014/06/04 职场文书
超市周年庆活动方案
2014/08/16 职场文书
英文演讲稿开场白
2014/08/25 职场文书
政府会议通知范文
2015/04/15 职场文书
公司员工辞职信范文
2015/05/12 职场文书
2019年幼儿园管理条例范本!
2019/07/17 职场文书