Bootstrap

8-file-saver下载文件地址后缀为.zip无法自定义文件名问题解决

前提条件:本地启动项目测试时使用file-saver插件的saveAs(url,filename)方法下载从后台获取的文件地址,并自定义默认文件名,结果发现后缀为.zip的文件虽然自定义了filename,但是弹出下载弹窗时没有生效,依旧是取文件地址中的文件名

过程:先找原因,在下载的文件地址中,图片类的文件地址自定义文件名是生效的,只有.zip类型的文件地址没有生效,但理论上无论是图片类文件还是ZIP类文件,自定义文件名都应该能够生效。

查阅资料后,我认为可能的原因如下:

(1)虽然大多数现代浏览器都支持saveAs,但不同浏览器对文件下载的处理方式可能有所不同。某些浏览器可能在处理ZIP文件时存在特定的行为或限制。

(2)某些浏览器可能会根据HTTP响应头中的Content-Disposition字段来设置文件名,而不是完全依赖saveAs中指定的文件名。这可能导致在ZIP文件下载时,自定义文件名不生效。

浏览器的行为差异,我们没办法插手,而Content-Disposition字段是服务器配置的内容,前端也无法修改,所以只能另找其他方法

而,saveAs()方法中的url可接收blob、file、url三种形式,既然url试不通,也无法直接拿到file,那就让它变成blob试试

让url转成blob,可以使用axios的get请求,设置responseType为blob,获取返回数据,代码如下:

    downloadFile(url, filename) {
      axios
        .get(url, { responseType: "blob" })
        .then((res) => {
          return res.data;
        })
        .then((blob) => {
          saveAs(blob, filename);
        })
        .catch((err) => {
          console.error("Error:", err);
        });
    },

结果一请求就出现了跨域的问题

那就只能上跨域的解决方法了,最常见的前端跨域解决方法就是代理

在vue.config.js配置如下(简单配置):

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  devServer:{
    proxy:"http://112.xxx.xxx.xxx:xx/"//不好写全,总之就是把请求跨域的那个IP端口写上
  }
})

然后需要替换文件地址中的ip端口为本地运行的ip端口,直接localhost:8080这样也行

最后实现能自定义文件名了

这个示例只是在本地运行的时候会报跨域错误,放上服务器可能就不会了

有个很搞笑的事情就是,我在做了跨域后直接使用saveAs()方法下载.zip的文件,结果它自定义文件名又生效了,没配置前就不生效,配置了之后就生效了,兜兜转转,感觉回到了起点。

不过还是要记录一下,或许saveAs在服务器上能顺利使用,而在本地运行的环境去下载服务器上的文件可能就有点小插曲,牢记教训就好。

坚持就是胜利!

;