当前位置:   article > 正文

解决因跨域导致使用a标签下载文件download属性失效无法自定义命名的问题_a标签download属性无效

a标签download属性无效

问题背景:

在使用a标签下载文件时,download属性可以更改下载的文件名

  1. // 下载a.exe,并采用默认命名
  2. <a href="/images/a.exe" download>点击下载</a>
  3. // 将a.exe改名为b.exe下载
  4. <a href="/images/a.exe" download="b">点击下载</a>

但是当a标签的下载链接跨域时,download属性将不会生效,原因是浏览器无法获取到文件,不能对他进行更改。

在这种情况下如果你是下载浏览器无法解析的文件,例如.exe,.xlsx..那么浏览器也会自动下载,但是如果你使用浏览器可以解析的文件,比如.txt,.png....浏览器就会采取预览模式,无法直接下载。

  1. // 无法正常下载a.jpg,会直接预览
  2. <a href="https://www.baidu.com/a.jpg" download>点击下载</a>
  3. // 正常下载a.exe文件
  4. <a href="https://www.baidu.com/a.exe" download>点击下载</a>

注意:

html5 新特性a标签download属性只支持谷歌和火狐
在谷歌和火狐浏览器a标签download属性修改文件名失效的原因:不同源,访问的域名和href的域名要一致。

a标签属性文档<a>:锚元素 - HTML(超文本标记语言) | MDN

什么是同源url:

 解决方法:

使用Blob实现文件下载,先把文件以bobl的形式下载到当前页面,再创建a标签。

  1. // 下载url(解决跨域a.download不生效问题)
  2. downloadFile(url, fileName) {
  3. const x = new XMLHttpRequest()
  4. x.open("GET", url, true)
  5. x.responseType = 'blob'
  6. x.onload = function(e) {
  7. const url = window.URL.createObjectURL(x.response)
  8. const a = document.createElement('a')
  9. a.href = url
  10. a.target = '_blank'
  11. a.download = fileName
  12. a.click()
  13. a.remove()
  14. }
  15. x.send()
  16. },

 使用方法:

  1. <el-link
  2. :disabled="validateNull(fileUrl)"
  3. :type="validateNull(fileUrl) ? 'info' : 'primary'"
  4. :underline="true"
  5. style="font-size:14px;"
  6. @click="downloadFile(fileUrl, fileName)"
  7. >
  8. {{ fileName|| '-' }}
  9. </el-link>

这里的validateNull是校验url是否为空:

  1. /**
  2. * 判断是否为空
  3. */
  4. export function validatenull(val) {
  5. if (typeof val === 'boolean') {
  6. return false;
  7. }
  8. if (typeof val === 'number') {
  9. return false;
  10. }
  11. if (val instanceof Array) {
  12. if (val.length===0) return true;
  13. } else if (val instanceof Object) {
  14. if (JSON.stringify(val) === '{}') return true;
  15. } else {
  16. if (val==='null' || val===null || val==='undefined' || val===undefined || val==='') return true;
  17. return false;
  18. }
  19. return false;
  20. }

这个下载方法有个需要注意的问题就是,当自定义的fileName内存在小数点时(如 fileName = '附件v1.2.zip'),如果没有在fileName后面加上后缀名(fileName = '附件v1.2'),会导致下载时自动以第一个小数点后面的为文件后缀名(.2),所以这时还要加一个方法判断文件的后缀名,将后缀名加到自定义的文件名后面:

  1. function getFileTypeByPath(pathUrl) {
  2. let index = pathUrl.lastIndexOf(".") // lastIndexOf(".") 找到最后一个 . 的位置
  3. let fileType = pathUrl.substr(index + 1) // substr() 截取剩余的字符,即文件后缀名 doc 、jpg 、 xlsx 等
  4. return fileType
  5. }

此时我们传入的fileName为:

  1. const suffix = this.getFileTypeByPath(fileUrl)
  2. this.suffix = `.${suffix}`
  3. const fileName = '附件v1.2'
  4. this.fileName = `${fileName}${this.suffix}`

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号