谈一谈url实现文件下载

前几天,一个关于下载的问题,把我困在原地蛮久,记录一下。

说到标题,后台返回一个url,前端浏览器打开实现下载功能,直接想到的就是window.open(url) 来实现下载,但是这种方法 我个人认为一闪而过的白色页面导致用户体验不是很好, so,就随手写写。

  • 1 window.location.href = url;
  • 2 a标签下载,栗子

可以使用download属性指定下载下来的文件名

  我在vue中,因为是导出,url参数根据页面的选择项而变化,点击button,生成一个url,a标签的href属性绑定url,之后

<a :href="downloadUrl" style="display: none" ref="download"></a>  // a标签隐藏
this.$nextTick(() => { 
  this.$refs.download.click()
})  这种的写法代替了jquery的trigger事件
  •  3  form下载
/**
 * 兼容性的下载方式,调用浏览器的下载功能
 * 使用该方法需要跟后台协商好传递token的字段名为access_token
 * @param url 文件下载请求的url
 * @param token 传递的token
 * @param input 传递的其他参数 [{name: 'reportPath', value: '/conc/report/201710300735080796.doc'}, {name: 'isOnline', value: false}]
 */
const downloadFile = (url, token, input = []) => {
  var $form = document.createElement('form')
  var $input = document.createElement('input')
  if (token) {
    $input.setAttribute('type', 'hidden')
    $input.setAttribute('name', 'access_token')
    $input.setAttribute('value', token)
  }
  $form.setAttribute('method', 'get')  // or post
  $form.setAttribute('action', url)
  $form.appendChild($input)
  for (var i = 0; i < input.length; i++) {
    var _input = document.createElement('input')
    _input.setAttribute('type', 'hidden')
    _input.setAttribute('name', input[i].name)
    _input.setAttribute('value', input[i].value)
    $form.appendChild(_input)
  }
  document.body.appendChild($form)
  $form.submit()
  $form.addEventListener('submit', function (e) {
    e.preventDefault()
  })
  document.body.removeChild($form)
}

但是这种方法的体验我感觉最好,但是是有限制的,如果你以get请求形式下载,url后面的?参数会全部被截取,我之前就是采用这种方式进行导出,结果才发现了这个问题。采取以上方式最好的url参数不是?携带,而是 以http://XXXX/${参数}的形式最好

  • 当为get请求时,请求所需的参数用input标签来传递,直接写在url后面是无效的。
  • 当为post类型时,queryString参数直接写在URL?后面,formData参数则用input标签传递  

个人认为参数过多,就很麻烦了,因为要传多少数据就得用多少input标签。post请求的时候,如何后台需要指定content-type,form做不到

  • 4 iframe下载

这种方式,就是如果给了多个url,他都可以给你下载下来,还能指定下载下来的文件名,栗子

 for (let i = 0; i < this.dataList.length; i++) {
          let url = this.dataList[i].contractSignUrl
          let token = cache.get('TOKEN').Authorization
          let ifr = document.createElement('iframe')
          ifr.style.display = 'none'
          ifr.src = url + '?access_token=' + token
          document.body.appendChild(ifr)
          // 保存页面 -> 保存文件
          ifr.contentWindow.document.execCommand('SaveAs', false, this.dataList[i].contractName)
        }

如果有什么不对之处,希望大家能指出来,谢谢。

猜你喜欢

转载自blog.csdn.net/shentibeitaokong/article/details/83687396