文件下载

目前通常可以通过两种方式下载

服务端读取文件

public String readFileToString(String fullPath) throws Exception {
        String encoding = "UTF-8";
        File file = new File(fullPath);
        Long filelength = file.length();
        byte[] filecontent = new byte[filelength.intValue()];
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            in.read(filecontent);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("readToString", e.getMessage(), e);
                }
            }
        }
        try {
            return new String(filecontent, encoding);
        } catch (UnsupportedEncodingException e) {
            logger.error("readToString", e.getMessage(), e);
            return null;
        }
    }

下载的方式

URL链接的方式

  • window.location.href=url;当前网页下载
  • window.open(URL) 在新打开的页面下载,防止在当前网页下载存在问题时,当前页面跳转到错误提示页面,新的页面下载不影响当前页

let url = this.$http.defaults.baseURL + “/download_file2?type=” + type + “&fileName=” + fileName

以blob的方式

该方式是通过xhr请求的方式下载的,可以获取到返回文件的同时,还可以获取其他相关信息,并且给出明确提示,是文件未找到还是其他情况


axios({
    method: 'get',
    url: '/download_file',
    params: param,
    responseType: 'blob'//blob
}).then((res) => {
    console.log(res);
    if (200 == res.status && res.data && res.data instanceof Blob) {
        let docType = res.headers['content-type'];
        let blob = new Blob([res.data], {type: docType});
		//在header中可以默认取到'Content-Type'
		//但是排除一些默认的可以取到的值其他文件都需要特殊设置
		//注意获取该值需要在服务端设置:response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
		//这里需要注意一点,有坑,字段的大小写不一样,在本地的时候'content-disposition',但是生产或其他环境就是'Content-Disposition',所以需要两种都写上,否则总有一方拿不到值
        let contentDis = res.headers['Content-Disposition'] || res.headers['content-disposition'];
        if (!!window.ActiveXObject || "ActiveXObject" in window) {//兼容IE10 11
            try {
                let fileName = contentDis.split('filename=')[1];
                navigator.msSaveBlob(blob, fileName);
                // navigator.msSaveOrOpenBlob(blob, fileName);//下载没有后缀名的文件存在安全限制,需要调低安全级别
            } catch (e) {
		  //改方式是通过浏览器网址直接下载,为了兼容无后缀文件在IE中的下载
                console.log("IE problem");
                console.log(e);
		    console.log(url)
		  // window.open(url);
                window.location.href = url;
            }
        } else {
            try {
                console.log(res.headers['Content-Disposition']);
                console.log(res.headers['content-disposition']);
                console.log(contentDis);
                let fileName = contentDis.split('filename=')[1];
                console.log(fileName);
                vv.downFileDirectly(blob, fileName);
            } catch (e) {
                console.log("Chrom problem");
                console.log(e);
            }
        }
    }
}).catch((e) => {
    console.log(e);
});


downFileDirectly(blob, fileName) {
    let downloadElement = document.createElement('a');
    let href = window.URL.createObjectURL(blob); //创建下载的链接
       downloadElement.href = href;
    downloadElement.download = fileName;//this.recordData.fileName;//下载后文件名
       document.body.appendChild(downloadElement);
    downloadElement.click(); //点击下载
       document.body.removeChild(downloadElement); //下载完成移除元素
        window.URL.revokeObjectURL(href); //释放掉blob对象
},

注意事项
1.服务器端返回的文件数据类型
一般情况下,服务端返回的是二进制的数据类型,该方式是blob类型
服务器端仅仅是在通过window.location.href下载的文件格式的基础上添加设置:response.setContentType(“application/octet-stream”);
2.接收文件数据
服务器端返回的整个reponse.data 就是整个文件数据
一般的交互中,获取的数据一般都是在reponse.data.data中
3.其他参数
content-type:获取的文件类型
该值一般我们从res.headers[‘content-type’]中获取,前端根据服务端设置的该文件类型值,对接受的文件转化为对应的数据类型
该值只要服务端设置了值,我们直接就可以从headers中获取,不需要服务另外授权;

因为有些值需要服务端授权,前端才可以取到对应的值,否则哪怕你从客户端浏览器看到了该值,你一样无法通过代码去获取到该值
Content-Disposition|content-disposition:获取的文件名,该文件名包括文件的后缀名
1)该值前端的获取,需要服务端授权 --response.setHeader(“Access-Control-Expose-Headers”, “Content-Disposition”)
2)该值在不同运行环境中取值的字段稍有不同
本地运行的环境获取该值-- res.headers[‘content-disposition’]
生产/UAT等其他非本地的服务器环境获取该值-- res.headers[‘Content-Disposition’]
因此为了该区值能同时兼容线上环境与本地的运行环境,通过以下总会获取到值–let contentDis = res.headers[‘Content-Disposition’] || res.headers[‘content-disposition’];
4.下载文件的保存

  • IE
    • navigator.msSaveBlob(blob, fileName);
    • navigator.msSaveOrOpenBlob(blob, fileName);(IE不支持createObjectURL)
  • 其他浏览器
    • window.URL.createObjectURL(blob)

对于有后缀的文件两种方式均可以正常下载,无后缀的文件却无法正常下载;
这里的无后缀不是指下载后的文件没有后缀名,这个没有后缀名可能是服务端的失误,例如 book.xml,在传给你文件名字的时候漏掉了后缀名,只传了book给你 ;
无后缀文件这里指的是被下载的文件本身是没有后缀名的,将要被下载的文件就是:book

两种方式的不同点:

服务端以是blob的方式需要服务端设置response.setContentType(“application/octet-stream”);

两种方式的相同点:

都是接受的文件字节,byte[],获取文件的方式完全相同,读取文件的方式也相同

下载无后缀的文件:

通过window.location.href 的方式下载文件,chrome是禁止下载,提示如下:
在这里插入图片描述
但是chrom支持blob的方式下载无后缀方式,不支持URL的方式下载无后缀

本人最开始遇到的现象是IE是完全相反的,支持URL的方式下载无后缀,不支持blob的方式,但是后来不知道为什么IE通过URL下载无后缀文件也不支持了

IE禁止下载,提示如下:

目前在线上环境上通过下载其他服务器上的字节流可以正常下载,但是同一项目接口未正常下载

无后缀可以正常下载,改方式为blob文件方式
http://10.67.37.68:9099/file/234
http://10.67.37.68:9099/file/文件名
文件名有无后缀均可正常下载

尝试修改本地对应IP对应的域名:

C:\Windows\System32\drivers\etc

hosts文件添加:
10.67.37.68 prefix.sit.dnscfc.cn

cmd终端刷新dns
ipconfig /flushdns

ipconfig /displaydns

访问:
http://prefix.sit.dnscfc.cn:9099/file/234
http://prefix.sit.dns.cn:9099/file/234
http://prefix.dns.cn:9099/file/234
弹出安全提示不可下载

访问
http://prefix.sit.dnscfc.com:9099/file/234
http://prefix.sit.dnscfc.cn1:9099/file/234
http://prefix.sit.dnsgc.cn:9099/file/234

可以下载,发现dns或者dns与cn的组合不被破环都不能下载,其他都可以正常下载,貌似是该域名被限制下载无后缀的文件了,这个估计只能让安全部门放开限制

但是也仅仅是貌似,因为感觉被忽略了一点是一开始无后缀的文件在IEwindow.location.href是可以被正常下载的。。。。
现在测试的为何不可下载,或许开始可下载的情况只是有后缀名的文件,只是后端在传递文件名时少了后缀名?不太确定了

包括URL下载与blob下载的说明与需要注意的事项,并包括关于无后缀文件的下载与分析,服务端对文件的读取,前端的接收处理等

资料

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三知之灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值