0


前端文件下载方式总结

写在前面:网上关于前端实现文件下载的文章已经有很多了,而且有的写的十分详细专业。之前一直不愿意做此类记录,一来是觉得这方面的文章太多太详细了,没有写的必要;二来是想着自己写的还不一定有别人写的好。但随着日常开发中用到的文件下载功能用的越多,各种下载方式都有使用过,觉得需要记录一下,以方便使用。

1、form 表单下载

1.1、表单下载基本使用

form 表单下载是比较传统的下载方式,话不多说,直接看实例:

  1. function formDownload(data){ // data :<object> form 表单的传参
  2. let form = document.createElement('form');
  3. form.id = 'idForm';
  4. form.name = 'name_form';
  5. form.style.display = 'none';
  6. document.body.appendChild(form);
  7. for (let i in data) {
  8. if (i !== 'action') {
  9. let input = document.createElement('input'); //创建 input 标签并传入 form 中,作为 form 的表单的发送参数
  10. input.type = 'text';
  11. input.name = i;
  12. input.value = data[i];
  13. form.appendChild(input);
  14. } else {
  15. continue;
  16. }
  17. }
  18. form.method = 'get';
  19. form.action = URL; // form 表单发送的地址
  20. form.submit();
  21. document.body.removeChild(form);
  22. }
  • 表单的提交就相当于一次请求,input 中的值相当于传参
  • form 上有一个属性 target,这个属性指定返回结果放的位置,默认 _self 表示本页面
  • 浏览器可以识别的文件不能下载:txt、png、jpg、gif等
  • 无法获取下载进度
  • 可以避免URL过长问题

1.2、 表单下载通过 iframe 接收返回信息并实现无刷新

将 form.target 设置成 iframe ,可以获取返回的信息,完整代码:

  1. function formDownload(data) { // data :<object> form 表单的传参
  2. var target = 'sub_frame' + Date.parse(new Date());
  3. var iframe = document.createElement('iframe');
  4. iframe.src = window.location.href;
  5. iframe.name = target;
  6. iframe.id = target;
  7. iframe.width = 0;
  8. iframe.height = 0;
  9. iframe.style.display = 'none'
  10. document.body.appendChild(iframe);
  11. let form = document.createElement('form');
  12. form.id = 'idForm';
  13. form.name = 'name_form';
  14. form.setAttribute("target", target);
  15. form.style.display = 'none';
  16. document.body.appendChild(form);
  17. for (let i in data) {
  18. if (i !== 'action') {
  19. let input = document.createElement('input'); //创建 input 标签并传入 form 中,作为 form 的表单的发送参数
  20. input.type = 'text';
  21. input.name = i;
  22. input.value = data[i];
  23. form.appendChild(input);
  24. } else {
  25. continue;
  26. }
  27. }
  28. form.method = 'get';
  29. form.action = URL; // form 表单发送的地址
  30. form.submit();
  31. document.body.removeChild(form);
  32. // 通过循环去拿返回数据
  33. var count = 0;
  34. var timer = setInterval(function () {
  35. var iframeObj = $(window.frames[target].document);
  36. var val = iframeObj.find("pre").text();
  37. count++;
  38. if (count >= 60) {
  39. window.clearInterval(timer);
  40. document.body.removeChild(iframe);
  41. return false
  42. }
  43. if (val) {
  44. var res = JSON.parse(val);
  45. window.clearInterval(timer);
  46. document.body.removeChild(iframe);
  47. }
  48. }, 1000)
  49. }

2、直接跳转下载

2.1、location.href

  1. window.location.href = url;

2.2、window.open

  1. window.open(url);
  • 以上两种适合 get 请求的单文件下载
  • 会出现 url 过长的问题,需要注意 url 编码
  • 浏览器可以识别的文件不能下载:txt、png、jpg、gif等

3、a链接下载

  1. let a = document.createElement('a');
  2. a.style = 'display: none';
  3. a.download = filename;
  4. a.href = url;
  5. document.body.appendChild(a);
  6. a.click(); // 触发a标签的click事件
  7. document.body.removeChild(a);

这种方式也无法解决浏览器可识别文件直接打开的问题,但是 HTML5 新属性 download 属性会解决这个问题。

但是也会有局限:部分情况下会出现跨域问题,此时还是浏览器预览而非下载,download属性失效。可以用这个方法试一下文本、图片。

部分浏览器由于兼容性问题(一般不会出现):

const isSupport = 'download' in document.createElement('a');

看支不支持 download 属性

** 4、文件流下载之 blob + a 链接 + blob URL**

  1. let xhr = new XMLHttpRequest();
  2. xhr.open('GET', videoUrl, true);
  3. xhr.responseType = 'blob';
  4. xhr.onload = function() {
  5. if (xhr.status === 200) {
  6. // 将视频Blob对象创建一个临时URL
  7. let videoBlob = xhr.response;
  8. let url = window.URL.createObjectURL(videoBlob);
  9. // 设置a标签的属性,并触发点击事件进行下载
  10. a.href = url;
  11. a.download = fileName; //文件名
  12. a.click();
  13. // 释放URL对象
  14. window.URL.revokeObjectURL(url);
  15. a.remove()
  16. }
  17. };
  18. xhr.send();

发送 http 请求,指定返回值类型是 blob 流

建议加上 download 的后缀名,避免极个别浏览器无法识别

这种实现本质是通过 blob URL方式

可通过 xhr.getResponseHeader("Content-Disposition") 获取 header 上的 Content-Disposition 属性,通过截取得到文件名

5、** 文件流下载之 blob + a 链接 + **readAsDataURL

  1. let xhr = new XMLHttpRequest();
  2. xhr.open('GET', videoUrl, true);
  3. xhr.responseType = 'blob';
  4. xhr.onload = function() {
  5. if (xhr.status === 200) {
  6. // 将视频Blob对象创建一个临时URL
  7. let videoBlob = xhr.response;
  8. const fileReader = new FileReader();
  9. fileReader.readAsDataURL(videoBlob);
  10. fileReader.onload = function () {
  11. const a = document.createElement('a');
  12. a.style.display = 'none';
  13. // 结果本质上是 base64 编码的 data URL 格式
  14. a.href = fileReader.result;
  15. a.download = name;
  16. document.body.appendChild(a);
  17. a.click();
  18. document.body.removeChild(a);
  19. }
  20. }
  21. };
  22. xhr.send();

这个方法和上个 方法都是获取 blob 形式的返回值,只是结果处理方式不同,这种方式是通过 readAsDataURL 生成 base64 编码的 Data URL 再通过连接下载。

两种方法都可以解决 浏览器直接打开无法下载的问题

标签: html5 javascript

本文转载自: https://blog.csdn.net/m0_67793437/article/details/139778587
版权归原作者 Wu Youlu 所有, 如有侵权,请联系我们删除。

“前端文件下载方式总结”的评论:

还没有评论