Z次元
文章 笔记 日志
专题
专栏分类 文章归档
友链
友情链接 朋友圈
留言
头像
系列文章
Vue(JavaScript)下载文件方式汇总
系列文章
前端知识积累
最后更新:2024/12/15|创建时间:2022/3/31
文章摘要
文章介绍了多种在Vue中下载文件的方法。每种方法均指出了其优缺点及适用场景,特别是跨域问题和在手机端浏览器的限制。还涉及了下载文字、图片、网络资源等特定场景下的处理技巧。

Window下载

实现原理:直接用浏览器访问下载链接,唤起浏览器下载功能

window.location.href = '下载链接';
// 或者
window.open('下载链接');

缺点:无法(从前端)自定义下载文件名,下载可预览文件(图片,音乐、视频等)时,会跳转新的界面

A标签下载

实现原理:创建一个a标签,然后点击它,即把下面的标签用js创建出来

<a href="下载链接" download="文件名(如:a.zip)">下载</a>

a标签download+url

const a = document.createElement('a')
a.href = '下载链接'
a.download = '文件名'
a.style.display = 'none'
a.target = 'downloadFile'
document.body.appendChild(a) // 兼容火狐 
a.click()
document.body.removeChild(a) // 移除a标签

缺点:下载可预览文件时,会跳转新的界面,对于跨域请求download属性会失效,也就是说无法自定义下载文件名

window.URL+blob

下载文件

由于上面是方法会打开新的界面,所以我们需要对下载链接进行一些处理,比如转为blob格式:

    // 这里需要发送一次请求将下载地址里的文件转为blob格式,进行下载(发送请求时同样会存在跨域问题,如果跨域的话需要在nginx配置代理)
    const blob = await fetch('下载链接').then(res => res.blob())
    content = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = content
    a.download = '文件名'
    document.body.appendChild(a) // 兼容火狐 
    a.click()
    document.body.removeChild(a) // 移除a标签
    window.URL.revokeObjectURL(content)  // 释放content对象

也可以用ajax请求转为blob格式:

      const x = new window.XMLHttpRequest()
      x.open('GET', '下载链接', true)
      x.responseType = 'blob'
      x.onload = () => {
          const content = window.URL.createObjectURL(x.response)
          const a = document.createElement('a')
          a.href = content
          a.download = '文件名'
          document.body.appendChild(a) // 兼容火狐 
          a.click()
          document.body.removeChild(a) // 移除a标签
          window.URL.revokeObjectURL(content)  // 释放content对象
      }
      x.send()

自然也可以发送axios请求:

  axios({
    method: 'get',
    url: '下载链接'
    responseType: 'blob',
  }).then((res) => {
    if (res && res.status === 200) {
      const content = window.URL.createObjectURL(new Blob([response.data]));
      const a = document.createElement('a') // 创建a标签
      a.href = content
      a.download = '文件名'
      document.body.appendChild(a) // 兼容火狐 
      a.click()
      document.body.removeChild(a) // 移除a标签
      window.URL.revokeObjectURL(content)  // 释放content对象
    }
  }

缺点:需要对下载链接进行请求,将下载的文件转为blob格式,所以自然少不了跨域问题,并且blob格式无法在手机端浏览器下载,所以建议和上面的配合使用,手机端用上面的url方法下载,电脑端用blob

下载文字

如果是文字的话,则无需再发送请求,可直接将文字转为blob格式

    const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
    // 只有上面的转为blob格式不同,下面的都是一样的
    content = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = content
    a.download = '文件名'
    document.body.appendChild(a) // 兼容火狐 
    a.click()
    document.body.removeChild(a) // 移除a标签
    window.URL.revokeObjectURL(content)  // 释放content对象

From表单下载

      const url = '下载地址'
      const form = document.createElement('form')
      form.style.display = 'none'
      form.setAttribute('target', '_blank')
      form.setAttribute('method', 'get')
      form.setAttribute('action', url)
      // 创建一个input控件:<input type="hidden" name="请求参数名" value="请求参数值"/>
      const input = document.createElement('input')
      // 设置input属性
      input.setAttribute('type', 'hidden')
      input.setAttribute('name', '请求参数名');
      input.setAttribute('value', '请求参数值');
  
      form.appendChild(input)
      document.body.appendChild(form)
      form.submit()
      document.body.removeChild(form)

下载可预览文件时,会跳转新的界面

Iframe下载

iframe下载不会出现向a标签那样的跳转问题,但是iframe兼容性较差,反正我在测试中没成功过

const url = '下载地址';
const iframe = document.createElement('iframe');
iframe.src = url;
iframe.style.display = 'none';
iframe.onload = function() {
    document.body.removeAttribute(iframe);
}
document.body.appendChild(iframe);

Canvas下载图片

      const url = '图片下载地址'
      const a = document.createElement('a')
      a.setAttribute('download', '文件名称')
      const image = new Image()
      // 添加时间戳,防止浏览器缓存图片
      image.src = url + '?timestamp=' + new Date().getTime()
      // 设置 crossOrigin 属性,解决图片跨域报错(还需要在后端设置允许跨域请求,否则仍会出现跨域问题)
      image.setAttribute('crossOrigin', 'Anonymous')
      image.onload = () => {
        // 将图片转为base64
        const canvas = document.createElement('canvas')
        canvas.width = image.width
        canvas.height = image.height
        const ctx = canvas.getContext('2d')
        ctx.drawImage(image, 0, 0, image.width, image.height)
        // 获取图片后缀名
        const extension = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase()
        // 部分图片地址可能没有后缀名,默认为png格式
        const base64Url = canvas.toDataURL('image/' + extension, 1)
        // 也可以直接写死后缀名
        // const base64Url = canvas.toDataURL("image/png")

        a.href = base64Url
        a.click()
      }

缺点:同样需要处理跨域问题

FileSaver下载文件

使用FileSaver下载文件时仍然存在跨域问题

下载:

npm install file-saver --save

# 或者:
bower install file-saver

引入:

import fileSaver from 'file-saver'

下载文字

var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
fileSaver.saveAs(blob, "hello world.txt");

下载图片(画布)

var canvas = document.getElementById("canvasid");
canvas.toBlob(function(blob) {
    fileSaver.saveAs(blob, "image.png");
});

下载网络资源

fileSaver.saveAs('地址', '名称')

下载文件(file)

var file = new File(["Hello, world!"], "hello world.txt", {type: "text/plain;charset=utf-8"});
fileSaver.saveAs(file);

下载文件(blob)

fileSaver.saveAs(blob, '文件名')

示例

转为blob格式的方法,上面已经写了很多个了,这里取其中一个做示范:

const blob = await fetch('下载链接').then(res => res.blob())
fileSaver.saveAs(blob, '文件名')
版权声明
本文依据 CC-BY-NC-SA 4.0 许可协议授权,请您在转载时注明文章来源为 Z次元 ,若本文涉及转载第三方内容,请您一同注明。
更多专栏文章推荐
前端知识积累
人非生而知之者,孰能无惑?惑而不从师,其为惑也,终不解矣。
Axios携带数据发送请求及后端接收方式
2022/3/25
跨域网络资源文件下载
2022/2/9
浏览器注入外部JS文件
2023/8/13
评论区

删除确认

评论删除后无法恢复,请确认是否继续?
发表评论

这里还没有评论哦

快来发一条评论抢占前排吧

Window下载
A标签下载
a标签download+url
window.URL+blob
下载文件
下载文字
From表单下载
Iframe下载
Canvas下载图片
FileSaver下载文件
下载文字
下载图片(画布)
下载网络资源
下载文件(file)
下载文件(blob)
示例
目录
Window下载
A标签下载
a标签download+url
window.URL+blob
下载文件
下载文字
From表单下载
Iframe下载
Canvas下载图片
FileSaver下载文件
下载文字
下载图片(画布)
下载网络资源
下载文件(file)
下载文件(blob)
示例
博客
文章 笔记 日志
专题
专栏分类 文章归档
友链
友情链接 朋友圈
交流
留言 关于我
主页
菜单
置顶
主题
我的
十玖八柒
每天进步多一点
欢迎到访φ(゜▽゜*)♪
最新评论
个人占星:
DeepSeek没有想象中的好用
个人占星:
想给自己的网站弄个统计功能,但不会弄,头疼
永恒末匕:
好哇塞,这个厉害
Corwin: @十玖八柒
哎 主要是我的个人网站用的是静态的cos 实现评论框还是有点困难
我的
关于我
个人主页
站点地图
RSS订阅
导航
十年之约
虫洞穿梭
开源博客
前端开源仓库
后端开源仓库
©2020 - 2025 By 十玖八柒 版权所有
豫ICP备20021466号