博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
php -- PHP实现点击a标签的href做链接时,直接保存文件(任何类型),而不是通过浏览器直接打开下载的文件...
阅读量:5840 次
发布时间:2019-06-18

本文共 1761 字,大约阅读时间需要 5 分钟。

之前做项目遇到这样一个问题,就是在php环境下,用a标签的href链接到一个资源,比如是mp3或者lrc文件时,点击之后不是出现保存文件的提示,而是调用本地程序打开文件或者直接在浏览器上解析。网上说可以全部做成rar格式的文件,这个一方面不方便,有些情况下也不可能完全这样做,还有实际上,做过测试会发现,在content-type:text/html的情况下,即时是rar有时也会被浏览器直接解析,无法实现下载的功能,那这个问题是不是就无解了呢?答案是否定的,几番搜索+测试,终于发现了一个可行的解决方案,就是在点击a标签的链接之后,不是直接请求资源,而是对header做一下预处理,再去readfile就可以了。下面附上相关的测试代码:

一、

index.php中:

下载"?>

process.php中:

这是最简单的方法,但是有个问题:如果请求的路径中包含中文,那么下载的文件名有可能就是乱码。

 

二、

针对上面问题的解决方案,

index.php中:

下载"?>

process.php中:

输出的时候,如果是Apache+PHP,那么还需要发送到Apache的输出缓冲区,最后才发送给用户。而对于Nginx+fpm,如果它们分开部署的话,那还会带来额外的网络IO。

 

三、

现在貌似没有问题了,但是readfile还是有问题的,虽然PHP的readfile尝试实现的尽量高效,不占用PHP本身的内存,但是实际上它还是需要采用MMAP(如果支持),或者是一个固定的buffer去循环读取文件,直接输出。

那么能不能绕过PHP这层呢,直接由webserver把文件发送给用户呢?可以的,我们可以使用Apache的module mode_xsendfile,让Apache直接发送这个文件给用户。

代码实现如下:(process.php)

header("Content-type: application/octet-stream");//处理中文文件名$ua = $_SERVER["HTTP_USER_AGENT"];$encoded_filename = urlencode($_GET['filename']);$encoded_filename = str_replace("+", "%20", $encoded_filename);if (preg_match("/MSIE/", $ua)) {header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');} else if (preg_match("/Firefox/", $ua)) {header("Content-Disposition: attachment; filename*=\"utf8''" . $_GET['filename'] . '"');} else {header('Content-Disposition: attachment; filename="' . $_GET['filename'] . '"');}//让Xsendfile发送文件  header("X-Sendfile: $_GET['filename']");

 

最后,如果愿意的话,可以先判断后缀,因为有时候图片当成文件下载也会引起一些不方便的:

$type = strrchr($_GET['filename'], "."); //获取后缀        if($type == "jpg" || "png" || "gif"){        header("Content-Disposition: filename=$_GET['filename']"); //这里我试过,加引号的话,下载时会加到文件名中        header("Content-Type: image/$type");        }

 

 

转自:http://m.blog.csdn.net/blog/nkliming/8536311

转载于:https://www.cnblogs.com/hf8051/p/4651906.html

你可能感兴趣的文章
设计模式之原则
查看>>
Maven修改全局和局部JDK版本
查看>>
设计模式——组合模式(Composite Pattern)
查看>>
java设计模式之——代理模式
查看>>
php页面防止重复提交
查看>>
Perl DBI模块的例子
查看>>
python中str和repr区别
查看>>
升级win10后无法使用桥接网络解决方法
查看>>
如何进行跨网段的远程唤醒
查看>>
数据挖掘-同比与环比
查看>>
nginx+php详解
查看>>
怎样取php一个字符串中的某个字符
查看>>
我的友情链接
查看>>
RedHat6 管理应用服务【11】
查看>>
stm32F10x复习-1
查看>>
redis的学习使用(ubuntu系统下)
查看>>
20135226黄坤信息安全系统设计基础期末总结
查看>>
轻松快捷创建VSFTP虚拟用户
查看>>
[转]Javascript原型继承
查看>>
[转] vue异步处理错误
查看>>