react+fetch+流的下载(后端返回的流的情况下的处理)

876 阅读1分钟

第一种方式通过我们的fetch请求数据,然后通过res.blob()方法解析我们的流,然后使用createObjectURL方法处理生成一个链接,然后下载

  • 缺点: 虽然能下载但是还是不能获取到后端返回的文件流的名字
fetchScream = async(params) => {
    try {
      fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(params),
      })
        .then(res => {
          return res.blob()
        })
        .then(data => {
          let blobUrl = window.URL.createObjectURL(data);
          this.download(blobUrl, '考核详情');
        });
    } catch(e) {
      Alert.show({ type: 'warning', title: `下载失败`, duration: 5 });
      console.log(e);
    } finally {

    }
}

download = (url) => {
    let userAgent = window.navigator.userAgent; // 取得浏览器的userAgent字符串
    if (userAgent.indexOf('Firefox') > -1) { // 判断是否Firefox浏览器
      let a = document.createElement('a');
      a.setAttribute('href', url);
      a.setAttribute('download', '下载文件的名字');
      document.body.appendChild(a);
      a.click();
    } else {
      let a = document.createElement('a');
      a.href = url;
      a.download = '下载文件的名字';
      a.click();
    }
}

改进,获取到的流通过res.blob()方法解析之外还对header后端返回的filename进行了获取

async function downLoadFile(url,params,name){
  try{
    // 解构了流和fileName
    let [fileBlob, fileName] = await fetch(url,{
      credentials: 'same-origin',
      body: JSON.stringify(params),
      method: 'POST',
      headers:{
        "Content-Type":"application/json"
      }
    }).then( response => Promise.all([
      response.blob(),
      response.headers.get('content-disposition'),
    ]));
    
    if(fileName && fileName !== null){
      fileName = decodeURI(fileName).slice('attachment;filename='.length);
      let objectUrl = URL.createObjectURL(fileBlob);
      let anchor = document.createElement('a');
      anchor.setAttribute('href', objectUrl);
      anchor.setAttribute('download', name);
      document.body.appendChild(anchor);
      anchor.click();
      document.body.removeChild(anchor);
      setTimeout(() => {
        URL.revokeObjectURL(objectUrl);
      }, 10000);
    }else{
      Alert.error("未查到相关数据");
      return;
    }
  } catch(e){
    console.log(e);
    Alert.error('导出失败')
  }
}