2022-10-fetch获取图片的md5值
1. 需求场景
拿到一个图片的MD5值。
2. 思路
http请求图片地址,拿到二进制数据,再计算md5值。
3. 实现方式
3.1 img标签
export const md5Image = (imagePath: string) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.setAttribute('crossOrigin', 'Anonymous');
img.src = imagePath;
img.onload = (e) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const w = img.width;
const h = img.height;
canvas.width = w;
canvas.height = h;
context && context.drawImage(img, 0, 0, w, h);
const type = 'image/jpg';
// 将canvas元素中的图像转变为DataURL
const dataurl = canvas.toDataURL(type);
// 抽取DataURL中的数据部分,并进行Base64解码
const bin = atob(dataurl.split(',')[1]);
// 创建空的Uint8Array
const buffer = new Uint8Array(bin.length);
// 将图像数据逐字节放入Uint8Array中
// eslint-disable-next-line no-plusplus
for (let i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
// 利用Uint8Array创建Blob对象
const blob = new Blob([buffer.buffer], { type });
const fileReader = new FileReader();
fileReader.readAsBinaryString(blob);
// 提取成功
fileReader.onload = (evt: any) => {
if (evt.target.readyState === FileReader.DONE) {
// 二进制数据结果
const imgFlag = evt.target.result;
// 进行md5加密
const spark = new SparkMD5();
spark.appendBinary(imgFlag);
resolve(spark.end());
}
};
};
});
};
这种方式因为图片的二进制流是从canvas中拿出来的,可能跟真实的图片有误差,导致不准确。
3.2 xmlhttprequest
export const md5ImageByXMLRequest = (imagePath: string) => {
return new Promise((resolve, reject) => {
const xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', imagePath, true);
xmlhttp.responseType = 'blob';
xmlhttp.setRequestHeader('Access-Control-Allow-Origin', '*');
xmlhttp.onerror = (e) => {
// console.error('md5-image', e);
reject();
};
xmlhttp.onload = function () {
if (this.status === 200) {
const blob = this.response;
const fileReader = new FileReader();
fileReader.readAsBinaryString(blob);
// 提取成功
fileReader.onload = (evt: any) => {
if (evt.target.readyState === FileReader.DONE) {
// 二进制数据结果
const imgFlag = evt.target.result;
// 进行md5加密
const spark = new SparkMD5();
spark.appendBinary(imgFlag);
resolve(spark.end());
}
};
fileReader.onerror = (e) => {
console.error(e);
reject();
};
}
};
xmlhttp.send();
});
};
这种写法没问题,但和fretch相比不简洁。
3.3 fetch
export const md5ImageByFetch = (imagePath: string) => {
return new Promise((resolve, reject) => {
fetch(imagePath).then((res: any) => res.blob()).then((blob: any) => {
const fileReader = new FileReader();
fileReader.readAsBinaryString(blob);
// 提取成功
fileReader.onload = (evt: any) => {
if (evt.target.readyState === FileReader.DONE) {
// 二进制数据结果
const imgFlag = evt.target.result;
// 进行md5加密
const spark = new SparkMD5();
spark.appendBinary(imgFlag);
resolve(spark.end());
}
};
fileReader.onerror = (e) => {
console.error(e);
reject();
};
});
});
};
4. fetch的response
上面的方法用到了response的blob方法。response有很多的属性和方法如下:
- Response.ok: 返回一个布尔值,表示请求是否成功,true对应 HTTP 请求的状态码 200 到 299,false对应其他的状态码。
- Response.status:返回一个数字,表示 HTTP 回应的状态码(例如200,表示成功请求)。
- Response.statusText:返回一个字符串,表示 HTTP 回应的状态信息(例如请求成功以后,服务器返回"OK")。
- Response.url: 返回请求的 URL。如果 URL 存在跳转,该属性返回的是最终 URL。
- Response.type: 返回请求的类型。可能的值如下:
basic:普通请求,即同源请求。
cors:跨域请求。
error:网络错误,主要用于 Service Worker。
opaque:如果fetch()请求的type属性设为no-cors,就会返回这个值,详见请求部分。表示发出的是简单的跨域请求,类似<form>表单的那种跨域请求。
opaqueredirect:如果fetch()请求的redirect属性设为manual,就会返回这个值,详见请求部分。
- Response.redirected: 返回一个布尔值,表示请求是否发生过跳转。
- Response.headers: 对应 HTTP 回应的所有标头,其属性有:
Headers.get():根据指定的键名,返回键值。
Headers.has(): 返回一个布尔值,表示是否包含某个标头。
Headers.set():将指定的键名设置为新的键值,如果该键名不存在则会添加。
Headers.append():添加标头。
Headers.delete():删除标头。
Headers.keys():返回一个遍历器,可以依次遍历所有键名。
Headers.values():返回一个遍历器,可以依次遍历所有键值。
Headers.entries():返回一个遍历器,可以依次遍历所有键值对([key, value])。
Headers.forEach():依次遍历标头,每个标头都会执行一次参数函数。
- response.text():得到文本字符串。
- response.json():得到 JSON 对象。
- response.blob():得到二进制 Blob 对象。
- response.formData():得到 FormData 表单对象。
- response.arrayBuffer():得到二进制 ArrayBuffer 对象。