js 下载文件到本地 的方法,图片下载失败清缓存试下!!!

629 阅读3分钟

js 本地下载的 几种办法:

1、a标签的download属性 适用于同源url,非同源的会走浏览器默认行为
// 下载  通过a 标签 download 属性协助下载  
// 同源的可以自定义下载名称,非同源下载名称取url的名称, 所以最好下载url链接名称为文件名称
export const downloadFile = (url: string, name?: string): void => {
  const link = document.createElement('a');
  if (name) {
    link.setAttribute('download', name);
  }
  // 不同源的会走浏览器默认行为
  link.setAttribute('href', url);
  link.click();
  link.remove();
};
2、iframe 隐形下载
// iframe 隐形下载
// 不能自定义图片下载的名称
// 当时实验的时候 此方法也是网页下载, 大文件不推荐

/* dom 部分 用于下载 */
<iframe id='ifile' style={{ display: 'none' }}></iframe>


/* js部分 用于下载 */
export const doenloadFun = (url: string) => {
    const iframe: any = document.getElementById('ifile');
    iframe.src =  url + (url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment';
}

3、对于非同源的文件下载1 修改方法1, 此方法和iframe 隐形下载差不多
// 下载不同源文件 
// 通过创建get请求url 返回文件类型, 再走方法1下载 
// 此方法走浏览器下载
export const downloadFileDiffSource = (url: string, name: string): void => {
  const link = document.createElement('a');
  if (name) {
    link.setAttribute('download', name);
  }
  const newUrl = url + (url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment'
  link.setAttribute('href', newUrl);
  link.click();
  link.remove();
};
4、对于非同源的文件下载2 搭配方法1
// 下载不同源文件 
// 通过创建get请求url 返回文件, 再走方法1下载 
// 此方法须请求文件回来, 如果文件类型太大了占用资源, 容易卡住,大文件不推荐
export const downloadFileDiffSource2 = (url: string, name: string): void => {
  const x = new XMLHttpRequest();
  x.open('GET', url, true);
  x.responseType = 'blob';
  x.onload = () => {
    if (x.status !== 200) {
      console.log('下载异常!');
      return;
    }
    
    // 创建url 再走 a 标签 download 属性协助下载
    const url = window.URL.createObjectURL(x.response);
    downloadFile(url, name);
    URL.revokeObjectURL(url);
  };
  x.send();
};

总结: 下载大文件 尽量使用 url + response-content-disposition=attachment 这种浏览器下载, 浏览器对于大文件可以支持分片,能暂停、开始 省不少事,如果自己网页请求大文件,非常耗费资源,容易造成阻塞,不是很推荐

图片下载问题:

在下载图片时遇到了一个问题, 就是文件下载都能实现, 但是只有图片类型会下载失败 报strict-origin-when-cross-origin:

问题分析

1、原先存储库下载权限未开启 跨域

2、开启后还是失败,报strict-origin-when-cross-origin

3、图片有缓存

4、浏览器强刷 清除缓存再试, 成功了

最终结论是:浏览器存在跨域和非跨域的请求,导致缓存了非跨域的请求,后续跨域的请求用了浏览器缓存所以被浏览器跨域机制拦截了

解决办法浏览器缓存 对于图片浏览器缓存和业务上跨域的请求的建议,也推荐使用如下其中一个方案:

(1).使用Cache-Control头部关闭缓存,如在 COS 上传的时候加上头部Cache-Control:no-cache。

(2).设置 标签的 crossorigin 属性的值为 anonymous,强制图片每次请求都使用 XHR 的 CORS 请求。

(3).AJAX 请求图片的时候加上随机参数。

(4).开启vary