四种常用的前端下载文件方案

559 阅读2分钟

1. a标签

点击a 标签,可以直接下载其href属性对应的文件,文件名为download属性的对应值。 < a href = " /images/logo.png " download = " /images/logo.png " > 可以用js动态生成一个a标签,模拟点击事件进行下载。

缺点:不能获取成功事件和异常事件

export const useATagDownLoad = (fileName, objectUrl) => {
  const el = document.createElement('a');
  el.download = fileName;
  el.style.display = 'none';
  el.href = objectUrl;
  document.body.appendChild(el);
  el.click();
  document.body.removeChild(el);
};

2. form 表单

利用form表单的submit功能,可以实现文件的下载。

效果 :在 当前页面打开一个下载弹框,实现文件的下载。

缺点:不能获取成功事件和异常事件

export const useFormDownload = (url, params) => {
  // 导出表格
  const form = document.createElement('form');
  form.id = 'form';
  form.name = 'form';
  document.body.appendChild(form);
  for (const obj in params) {
    if (params.hasOwnProperty(obj)) {
      const input = document.createElement('input');
      input.type = 'hidden';
      input.name = obj;
      input.value = params[obj];
      form.appendChild(input);
    }
  }
  form.method = 'GET'; // 请求方式
  form.action = url;
  form.submit();
  document.body.removeChild(form);
};

3. window.open( url)

window.open(url)会打开一个新的窗口进行下载,下载成功后会自动关闭新窗口,通过监听新窗口的breforeunload事件,可以知道下载成功了。

缺点:不能获取异常事件。

 const net = await window.open(url);
 net.addEventListener('beforeunload', (e) => {
   // 下载成功了
   this.appraisalDownLoading = false;
 });
  

4. ajax + window.URL. createObjectURL + a标签

ajax请求拿到文件数据后,利用   window.URL.createObjectURL 创建文件的url,利用a标签下载这个url。

优点:可以知道下载成功,可以catch异常。

需要注意的是:我们使用http响应头的Content-Disposition:attachment; filename 中的finename当做文件名,后端一般是用utf-8编码,而Http 消息只能是 ASCII 编码,所以文件名可能会出现乱码情况,需要后端返回 urlencode 后的finename。

该方法参考博客:www.cnblogs.com/saryli/p/54…

import axios from 'axios';
import FileType from 'file-type';
export const downloadFile = (path, params) => {
  return axios.get(`${path}`, {
    params,
    responseType: 'arraybuffer',
  });
};

export const downloadToObjectUrl = (() => {
  return async (path, params) => {
    try {
      const res = await downloadFile(path, params);
      const { headers } = res;
      // 失败时返回的json
      if (headers && headers['content-type'].includes('json')) {
        throw new Error('fail');
      }
      const buffer = res.data;
      const result = await FileType.fromBuffer(buffer);
      const blob = new Blob([buffer], {
        type: result && result.mime,
      });
      const objectUrl = window.URL.createObjectURL(blob);
      const fileNameMatch = (res.headers['content-disposition'] || '').match(
        /filename="(.*)"/
      );
      return {
        fileHash: params.fileHash,
        fileName: fileNameMatch ? decodeURIComponent(fileNameMatch[1]) : '', // include suffix
        objectUrl,
      };
    } catch (e) {
      throw e;
    }
  };
})();

export const useFormDownload = (url, params) => {
  // 导出表格
  const form = document.createElement('form');
  form.id = 'form';
  form.name = 'form';
  document.body.appendChild(form);
  for (const obj in params) {
    if (params.hasOwnProperty(obj)) {
      const input = document.createElement('input');
      input.type = 'hidden';
      input.name = obj;
      input.value = params[obj];
      form.appendChild(input);
    }
  }
  form.method = 'GET'; // 请求方式
  form.action = url;
  form.submit();
  document.body.removeChild(form);
};

const { fileName, objectUrl } = await downloadToObjectUrl(url, params);
useATagDownLoad(fileName, objectUrl);