通过路径来下载文件的三种方式 本文以图片为例
为什么有的时候通过a 标签下载图片直接打开了图片呢?有的时候又是直接下载呢?
- 下载直接跳到对应的图片 ? a 标签的地址是外部的,会默认跳转到这个图片 即使设置了 a 的 download 依旧会跳转
- 直接下载了图片 图片是本机图片,或者是本域名图片 会直接下载 ;
瞄一眼结构以及对应的地址
第一种方案直接下载 有局限性
<a href="./005100-1592412660f973.jpg" download="" name="1212312313">本机图片下载</a>
本机图片下载 这个标签的链接为本地图片地址 点击 ‘本机图片下载’ 就可以直接下载
第二种方案 使用canvas 来下载 会比第一种方案好
先说思路在写代码,思路对了才能写出正确的代码
1,应为我们是通过链接下载的图片 先实例化一个 Image,因为 Image 里面有我们所需要的东西 (图片的宽高)
2,创建一个 canvas 通过 JavaScript 的 document.createElement 方法来创建 ,并且创建一个2D的
3,使用 ==canvas 的 drawImage()== 方法来把图片 画上去[drawImage](https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/drawImage)
4 , == canvas 的 toDataURL() == 方法返回一个包含图片展示的 data URI [toDataURL()]('https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL')
5,还是通过 a 标签来下载图片,在创建一个点击的方法这样 就不用 把创建的 a 追加到页面上去,直接调用方法下载图片即可
downloadIamge(imgsrc, name = '图片名称') {
//下载图片地址和图片名
let image = new Image();
// 解决跨域 Canvas 污染问题
image.setAttribute('crossOrigin', 'anonymous');
image.onload = function () {
let canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL('image/png'); //得到图片的base64编码数据
let a = document.createElement('a'); // 生成一个a元素
let event = new MouseEvent('click'); // 创建一个单击事件
a.download = name ; // 设置图片名称
a.href = url; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
};
image.src = imgsrc;
},
第三种方案 通过XMLHttpRequest 来进行下载
1 ,先创建 一个 XMLHttpRequest 并把类型设置为 blob
2, 把请求回来的 blob 的数据通过 URL.createObjectURL 方法转为本地的 blob 路基
3, MouseEvent 创建一个单击事件 执行下载方法
function dw(url){
const xhr = new XMLHttpRequest()
xhr.open('get',url);
// 把请求类型设置为 blob
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function(sues){
const data = xhr.response;
// 把请求回来的blob数据 转为 blob 本地路径 进行下载 这个样不会出现跨域问题
const imgurl =URL.createObjectURL(data)
const elemtA = document.createElement('a');
// 创建一个 单击事件
let event = new MouseEvent('click')
elemtA.setAttribute('download','');
elemtA.setAttribute('href',imgurl);
// 执行单击方法 这里调用此方法就可触发
elemtA.dispatchEvent(event);
}
}
内容进行下载,二进制流内容,或者文本内容
应用场景,前端在做报表导出时,后端一般往往是返回的是二进制流的形式
流的方式进行下载
思路
1.下载方式思路跟浏览下载方式是一样的,只不过内容是后端返回的,不是后端生成好返回的链接
2.通过Blob读取后端返回的二进制内容
createObjectURL 创建一个 blob URL进行下载
Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取
Blob语法
var aBlob = new Blob( array, options );
参数
-
array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings 会被编码为 UTF-8。
-
options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
- type,默认值为 “”,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
- endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: “native”,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 “transparent”,代表会保持 blob 中保存的结束符不变 Non-Standard
代码示例
const link = document.createElement('a');
let blob = new Blob(['后端返回的二进制数据'], { type: 'application/vnd.ms-excel' });
let objectURL = URL.createObjectURL(blob); // 创建URL blob:https://www.xxx.com/285f734a-0f3a-4f01-b1cc-b95b29d7fd05 此链接可以下载
link.href = objectURL;
link.download = '文件名称';
link.click(); // 调用点击事件,紧张自动点击
URL.revokeObjectURL(objectURL); // 释放内存
异常处理
由于后端返回的是二进制,后端在生成二进制流错误的时候也会生成二进制的错误流
如:{msg:‘生成错误’,code:200} 此内容也生成二进制,我们需要转为二进制为明文,给与用户提示
使用 TextDecoder
TextDecoder 接口表示一个文本解码器,一个解码器只支持一种特定文本编码,例如 utf-8、iso-8859-2、koi8、cp1261,gbk 等等。解码器将字节流作为输入,并提供代码点流作为输出。
异常处理代码示例
const enc = new TextDecoder('utf-8');
const ErrData = enc.decode(new Uint8Array('后端返回二进制错误内容'))
// 如果是返回内容为对象 需要转化下
const res = JSON.parse(enc.decode(new Uint8Array('后端返回二进制错误内容'))); //转化成json对象
console.log(res);
完整代码示例
try {
// 能够解析内容 就为后端生成二进制流错误
const enc = new TextDecoder('utf-8'), ErrData = enc.decode(new Uint8Array('后端返回二进制错误内容'));
// 如果是返回内容为对象 需要转化下
const res = JSON.parse(enc.decode(new Uint8Array(ErrData))); //转化成json对象
if(res.code === 400){
console.log('返回异常')
}
} catch (error) {
// 解析不出就为正常导出内容
const link = document.createElement('a');
let blob = new Blob(['后端返回的二进制数据'], { type: 'application/vnd.ms-excel' });
let objectURL = URL.createObjectURL(blob); // 创建URL blob:https://www.xxx.com/285f734a-0f3a-4f01-b1cc-b95b29d7fd05 此链接可以下载
link.href = objectURL;
link.download = '文件名称';
link.click(); // 调用点击事件,紧张自动点击
URL.revokeObjectURL(objectURL); // 释放内存
}
文本下载
思路
只需要把后端返回的内容替换成,从页面获取的内容即可,注意导出内容格式