最近做了一个下载pdf文档的需求,本以为使用HTML5中<a>标签的属性download就能简单搞定,不料IE竟然不支持这一简单粗暴的H5新特性,而是直接在网页中打开,

于是各种搜索之后得出以下结论:IE中下载文档时,要想直接下载而不是在浏览器中打开,就要给下载的请求添加一些header属性:

1、Content-Disposition: attachment; filename=filename
2、Content-Type: application/octet-stream;

现在以我做的项目为例,总结一下在IE中下载pdf等类型文档的方法:

1、服务器端语言:PHP

2、前端语言:Jquery

因为要设置header,所以只能走服务器

第一步:前端创建一个下载文件的按钮

<button class="btn btn-small btn-warning"  id="df">下载pdf文档</button>

这里面的class是bootstrap中的样式,用过bootstrap的人应该都很熟悉,这里不再赘述

第二步:给这个按钮添加点击事件,当点击该按钮时发起一个下载文档的请求给服务器

$("#df").click(function(){
$.ajax({
url:"downloadFile",
type : 'POST',
dataType : 'json',
success : function (m) {
if (m.status == 1) {
location.href = "downloadFile"
} else {
showAlert(m.info);
}
}
});
});

这里使用ajax请求,downloadFile为请求的服务端方法,当服务器接收到该请求之后就会做出响应,即下一步

第三步:服务器接受并响应请求

public function downloadHelp(){
/*设置文档的路径*/
$fileDir = SERVER_PATH . 'static/help/'; if (IS_POST) {
if (!is_dir($fileDir)) {
mkdir($fileDir, 0777, true);
} $filePath = $fileDir . '下载文档.pdf'; if (!is_file($filePath)) {
$this->ajax_return(0,"文档不存在");
} else if (!is_readable($filePath)) {
$this->ajax_return(0,"文档不可读");
} else {
$this->ajax_return(1);
}
} else {
$ua = $_SERVER["HTTP_USER_AGENT"];
$fileName = '下载文档.pdf';
$encoded_filename = urlencode($fileName);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
$url = $fileDir . $fileName;
$fileSize = filesize($url);
header("Cache-Control: private");
header("Content-Type: application/octet-stream;");
header("Accept-Ranges: bytes");
header("Accept-Length: " . $fileSize * 1024);
/*
* 根据浏览器设置下载文件名称为中文时的编码
*/
if (preg_match("/MSIE/", $ua) || strpos($ua,"rv:11.0")) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $fileName . '"');
} else {
header('Content-Disposition: attachment; filename="' . $fileName . '"');
} readfile($url);
exit;
}
}

上面代码中的方法其实是完成了两次客户端请求,

1、第一次请求方式是POST(可见js代码中的ajax请求),所以这时会判断文件是否存在以及是否具有读取权限等
2、第二次请求方式是GET,所以这时会根据第一次请求的结果决定下一步

(1)当staus="0",,提示"文档不存在" or "文档不可读"

   (2)当status="1",设置header,并输出文件

其中值得注意的是,当下载的文件名为中文,且字符编码是UTF-8时,要根据浏览器类型进行设置,否则会出现文件名乱码的情况,上面的代码中已解决该问题,但是方法不止这一种,

所以再贴出解决下载文件名中文乱码的两种方法:

公共部分:
$ua = $_SERVER["HTTP_USER_AGENT"];
$fileName = '下载文档.pdf';
$encoded_filename = urlencode($fileName);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
$url = $fileDir . $fileName; 第一种方法:
if (strpos($ua,"MSIE") || strpos($ua,"rv:11.0")) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (strpos($ua,"Firefox")) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $fileName . '"');
}else {
header('Content-Disposition: attachment; filename="' . $fileName . '"');
} 第二种方法:
if (preg_match("/MSIE/", $ua) || strpos($ua,"rv:11.0")) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $fileName . '"');
} else {
header('Content-Disposition: attachment; filename="' . $fileName . '"');
}

其实这两种方法本质上没什么区别,只是我在测试的过程中发现,通过 $_SERVER["HTTP_USER_AGENT"]获取的浏览器信息中,如果浏览器是IE(我用的是IE11),

就没有“MSIE”这个字符串,导致即便是IE,strpos($ua,"MSIE")方法的结果还是false,所以无法解决IE中的乱码问题,于是就用strpos($ua,"MSIE")和preg_match("/MSIE/", $ua) 两种方法,

并在两种方法中都加上 strpos($ua,"rv:11.0"),这样才能判断出是IE浏览器,也就能顺利解决IE中文件名称中文乱码问题了。

以上就是本次下载pdf文档的需求中总结出的,本以为是个很简单的功能,没想到当它涉及到浏览器时竟有如此多的学问。

最新文章

  1. DNS缓存
  2. jstl_fmt
  3. POSTMAN发起请求收到乱码 http 406错误
  4. C++和java多态的区别
  5. Visual Studio 2013小技巧
  6. JAVA 加减乘除
  7. 领域实体框架Rafy2 发布了
  8. IE样式兼容写法
  9. js的变量作用域
  10. PHP输出图片文件,实现浏览器缓存机制
  11. Git CMD - pull: Fetch from and integrate with another repository or a local branch
  12. 关于PHP参数的引用传递和值传递
  13. 基于最简单的FFmpeg包封过程:视频和音频分配器启动(demuxer-simple)
  14. Java核心-多线程-并发控制器-Exchanger交换器
  15. Android Studio 配置虚拟设备的镜像文件的存放路径
  16. is_valid校验机制
  17. Java中日期格式化SimpleDateFormat类包含时区的处理方法
  18. spring-boot 速成(1) helloworld
  19. TmsHttpClientUtil
  20. Docker容器学习与分享11

热门文章

  1. UVALive-3722 留个坑,为什么费马小定理求逆元不对??
  2. 1.前端数据可视化插件:Highcharts、Echarts和D3(区别)
  3. ArduinoUno和Leonardo的区别
  4. 用docker部署zabbix
  5. C# GDI+编程(二)
  6. 如何妥善处理WebBrowser对Javascript的错误问题,阻止JS弹出框,提高用户体验
  7. HBase的安装与配置
  8. sscanf linux-c从一个字符串中读进与指定格式相符的数据
  9. Luogu P2101 命运石之门的选择(分治+搜索)
  10. mac上开启22号端口