前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端用a标签实现静态资源文件(excel/word/pdf)下载

前端用a标签实现静态资源文件(excel/word/pdf)下载

原创
作者头像
用户4396583
修改2024-08-28 10:41:37
6830
修改2024-08-28 10:41:37

实际项目中一般都会有一个模版下载的功能,一般都由服务端提供一个下载接口,返回文件流或url地址,然后前端再处理成对应需要的类型的文件。

但是,也有可能服务端就不提供下载接口了,那么模版就可以保存在前端项目中。

本文就是基记录如何实现纯前端下载静态资源文件。

一、实现原理

主要使用a标签,通过动态创建一个包含 download 属性的 a 元素,触发点击事件实现。

在 html5 中,a 标签新增了 download 属性,包含该属性的链接被点击时,浏览器会以下载文件方式下载 href 属性上的链接。

例如:<a href="https://www.baidu.com" download="baidu.html">下载</a>

注意:利用a标签实现下载,会导致一个问题,当你下载图片的URL是远程图片url时,将不是下载该文件而是打开该文件。(本文主要演示获取本地资源然后下载,不涉及此中场景。)

二、适用场景

纯前端实现下载功能一般比较适合固定的文件,比如:excel/word/pdf 等固定模版,并不会和数据库有交互。

三、具体实践

1、编写方法

代码语言:javascript
复制
/**
 * 下载本地文件
 * @param {*} path 本地文件路径,注意:必须保存在public文件夹下
 * @param {*} name 下载后的文件名
 */
const downloadLocalTemplate = (path, name) => {
  let a = document.createElement('a');
  a.href = path;  // 如果后端返回文件地址,path值就是后端返回的地址
  a.download = name; // 设置下载文件文件名,要完整的文件名+后缀,比如:test.xlsx
  a.style.display = 'none';
  document.body.appendChild(a);
  a.click();
  a.remove();
};

2、调用

代码语言:javascript
复制
downloadLocalTemplate('/static/test.xlsx','test.xlsx')

downloadLocalTemplate('/static/test.pdf','test.pdf')

成功结果如下:

3、注意事项、

downloadLocalTemplate方法的path参数路径问题:

1、引用路径必须使用英文,防止打包引用地址错乱导致下载失败。

2、关于文件的存放:

  • 如果vue项目有public文件夹,可以直接将文件放到该目录下,或者新建一个static文件夹,将资源存放在该目录下。引用路径为:'文件名''static/文件名'
  • 如果vue项目没有public文件夹,但是有static文件夹,就将资源直接存放到static文件夹下,引用路径为:static/文件名

3、第一个参数的文件路径写法:必须是/绝对路径,不能是./相对路径。

对于vue项目,如果是将文件放到public文件下就直接写文件名,如:'test.xlsx’。

如果有二级目录public/static就直接写地址,如:'static/test.xlsx'

同时注意⚠️ 如果vue.config.js中配置了publicPath,需要在下载的文件地址前面加上配置的路前缀/,例如:'/static/test.xlsx'。

4、总结不能正常下载可能的原因:

a. 文件路径错误;

b. 文件编码问题,比如用excel文件,但是下载保存成了pdf文件。

c. 浏览器兼容问题,比如不支持a标签的download属性。

例如:出现如下结果,提示:无法从网站上提取文件 大概率都是文件路径的问题。

四、即使使用a标签的download属性,chrome浏览器还是会打开

追查问题原因:

服务器端返回的response中,content-type为text/plain,即数据以纯文本形式(text/json/xml/html)进行编码,其中不含任何控件或格式字符。chrome浏览器直接打开了该文本,并没有下载。

五、解决方案

解决方案一:使用ajax请求该url,获取到文本内容,手动实现下载。
代码语言:html
复制
<a onClick={() => { this.downLoad(href);}} disabled={href ? false : true}>
  下载执行结果
</a>
代码语言:javascript
复制
//js代码:
downLoad = url => {
//后面加上‘&’,防止请求时,url后面添加问号会影响原来的url参数值
    let newurl = url + "&";
    let fileName = url.slice(url.lastIndexOf("/") + 1, url.indexOf("?"));
    let result = '';
    fetchGet(newurl, {}, { credentials: "include" }).then(response => {
      result = JSON.stringify(response);
      var datastr = `data:text/json;charset=utf-8,${result}`;
      var downloadAnchorNode = document.createElement("a");
      downloadAnchorNode.setAttribute("href", datastr);
      downloadAnchorNode.setAttribute("download", fileName + ".json");
      downloadAnchorNode.click();
      downloadAnchorNode.remove();
    });
  };

解决方案二:设置Content-Type

chrome浏览器对与txt,json等文件直接打开应该是因为浏览器对这些类型的文件支持阅览,可以设置Content-Type:application/octet-stream来解决此问题,告知浏览器这是一个字节流,浏览器处理字节流的默认方式就是下载。

可以参考这个OSS文档

可以手动在OSS上设置这个类型,如果是公共读类型的文件也可以直接在链接后面加上,比如:window.open(‘https://xxx.json?response-content-type=application%2Foctet-stream’)

六、扩展:a标签download下载属性无效

跨域会导致download属性失效。可以试试xhr下载方式。

代码语言:javascript
复制
export default function download(url, fileName) {
    const x = new XMLHttpRequest()
    x.open('GET', url, true)
    x.responseType = 'blob'
    x.onload = () => {
      const url = window.URL.createObjectURL(x.response)
      createAndRemove(url, fileName)
    }
    x.send()
  }

  function createAndRemove(url, fileName) {
    // 创建隐藏的可下载链接
    var eleLink = document.createElement('a');
    eleLink.download = fileName;
    eleLink.style.display = 'none';
    // 下载内容转变成blob地址
    eleLink.href = url;
    // 触发点击
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然后移除
    document.body.removeChild(eleLink);
  }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、实现原理
  • 二、适用场景
  • 三、具体实践
    • 1、编写方法
      • 2、调用
        • 3、注意事项、
          • downloadLocalTemplate方法的path参数路径问题:
            • 解决方案一:使用ajax请求该url,获取到文本内容,手动实现下载。
        • 四、即使使用a标签的download属性,chrome浏览器还是会打开
        • 五、解决方案
        • 六、扩展:a标签download下载属性无效
        相关产品与服务
        云服务器
        云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档