PHP下载文件并重命名

背景:

有个需求是要求下载文件并将其改名,故当时将功能做至项目上,导致文件下载流程如下:

附件服务器  - 下载 - > 项目服务器- 改名 - > 用户

相当于下载了两个文件,再加上带宽附件服务器带宽2M,用户体验差,故考虑去掉中间步骤,用户直接向附件服务器请求文件。

服务器环境:

  • Windows Server 2008   
  • IIS 7  
  • PHP 5.4

过程:

pdf.js - > download2.js - > php

第一阶段:

pdf.js二次开发,做完回头一想,当时也是钻了牛角尖,但是也大体了解解其工作原理,了解Blob的一些知识;

思路:

先找JS文件中是哪里获取了文件名,进而切入改变其文件名,

在viewer.js中发现有变量名filename,故分析其为文件名,在下载方法中下断点,将其定值,下载名称改变,此处使用GetQueryString获取url中的参数值

function GetQueryString(name) {
          let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)","i");
          let r = window.location.search.substr(1).match(reg);
          if (r!=null) return (r[2]); return null;
      }

开始考虑自动下载,经过页面分析,发现右上方有下载键,故事考虑在window.onload中触发其点击。

触发点击下载:

window.onload = function () {
    document.getElementById("download").click();
}

测试在Chorme中通过,转至IE测试,发现名称不改变,于是开始追溯代码

在viewer.js 796行附近,追踪至下载方法,阅读代码发现程序先创建一个节点

var a = document.createElement('a');

然后根据浏览器版本来判断a.click方法,暂且不提

发现它默认使用的是download属性,然而IE全家都不支持,跳转至下面直接点击当前a对象,

在这个过程中发现下载触发的方法会根据文档是否加载完成变化,如果文档加载完成,点击下载是走的navigator.msSaveBlob方法,该方法是微软自家的MS,用的Blob对象,但是存在的问题,就是也是相当于先加载一遍他的二进制流,然后再下载,速度也是慢的,对于大文件就得等它加载完后才能触发下载,不合理。

然后一直寻找解决方法,不得其果。

第二阶段:

pdf.js就是一个预览插件,我为啥偏要在上面下断点,二次开发,遂将目标转移至js下载插件download2.js

代码如下:

<html>

<head>
<script src="build/download2.js"></script>
</head>
<body>
<script>
let filename_get = decodeURI(GetQueryString('file_name'));
let file_path = GetQueryString('file_path');
let x=new XMLHttpRequest();
x.open("GET", file_path, true);
x.responseType = 'blob';
x.onload=function(e){
    download(x.response, filename_get, 'application/pdf');
};

x.send();

function GetQueryString(name) {
    let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)","i");
    let r = window.location.search.substr(1).match(reg);
    if (r!=null) return (r[2]); return null;
}

</script>

</body>

</html>

随便点了几个发现好用了,chorme IE都可以,以为成了,洋洋得意之时,点了一个比较大的文件,没有反应,检查网络,发现报错:

net :: ERR_INSUFFICIENT_RESOURCES 200

经查,发现有可能是服务器请求大小限制,故上服务器修改配置,因为比较常用nginx或apache,对IIS并不是很了解,略微了解了一下,将system.web中的MaxRequestLength修改为400M,重启iisrestart ,测试失败,一样不下载,并且该方式有个问题,他也是需要先搞到js中,然后再发送xhr请求,文件比较大的时候会有一段的无反应时间,体验较差

综合以上几个原因故放弃

第三阶段:

目光转回PHP上,个人理解,js作为一种客户端语言,服务端的配置会十分限制其功能,故意视线转回老本行,在服务器上安装PHP,部署等不再赘述。

里面有个点,因为这个只有一个域名解析至这个服务器,懒得再申请了,于是配置的时候端口选择了82,不知道这样会不会有暴露端口的危险,但是对于服务器运维不是很了解,故先这样实现,以后有问题再修改附下载代码:

<?php
ob_clean();
$filename = $_GET['filename'];
$filename = urldecode($filename);//传的参数encode了


$filepath = '/';
if(!file_exists($filepath)){
    var_dump($filepath);
    exit;
}
$fp=fopen($filepath,"r");
$filesize=filesize($filepath);
header("Content-type:application/octet-stream");
header("Accept-Ranges:bytes");
header("Accept-Length:".$filesize);
header("Content-Disposition: attachment; filename=".$filename);
$buffer=1024;
$buffer_count=0;
while(!feof($fp)&&$filesize-$buffer_count>0){
    $data=fread($fp,$buffer);
    $buffer_count+=$buffer;
    echo $data;
}
fclose($fp);
?>

总结:

其实一开始不想用PHP解决的,单纯的用用js搞定,但是发现js基础还是薄弱哈哈,记录本次思路,以供后期翻阅。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值