前端很多场景下都有可能存在针对图片格式进行转换的情况,比如 canvas 绘制图片:
- 提供一个网络图片:
url->base64; - 接口希望是一个
Blob或者File文件流:Base64->Blob->File; - ... more...
一、url-> base64
export function getDataUri(url) {
return new Promise((resolve, reject) => {
let image = new Image();
// CORS 策略,会存在跨域问题 https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
image.setAttribute('crossOrigin', 'anonymous'); // 允许跨域获取该图片
image.crossOrigin = 'Anonymous';
image.src = url;
image.onload = function () {
let canvas = document.createElement('canvas'),
width = image.width, // canvas的尺寸和图片一样
height = image.height;
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(this, 0, 0, width, height);
// Data URI
resolve(canvas.toDataURL('image/png'));
};
// console.log(image.src);
image.onerror = () => {
reject(new Error('图片流异常'));
};
});
}
二、Base64 -> Blob -> File
/**
* @return Promise base64 转化成 blob
* @param {String} b64data base64
* @param {String} name 图片名称
* @param {String} type 图片类型 默认:image/jpeg、image/png...
*/
export function base64ToBlob(dataURL, name, type = 'image/jpeg', sliceSize = 512) {
const base64 = dataURL.split(',')[1];
return new Promise((resolve, reject) => {
// 使用 atob() 方法将数据解码
let byteCharacters = window.atob(base64);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
let slice = byteCharacters.slice(offset, offset + sliceSize);
let byteNumbers = [];
for (let i = 0; i < slice.length; i++) {
byteNumbers.push(slice.charCodeAt(i));
}
// 8 位无符号整数值的类型化数组。内容将初始化为 0。
// 如果无法分配请求数目的字节,则将引发异常。
byteArrays.push(new Uint8Array(byteNumbers));
}
let result = new Blob(byteArrays, {
type: type,
name,
});
result = Object.assign(result, {
lastModified: new Date().getTime(),
lastModifiedDate: new Date(),
name: name,
webkitRelativePath: '',
// 利用 URL.createObjectURL() 为 blob 对象创建临时的 URL
preview: URL.createObjectURL(result),
});
// Blob -> File
const newFile = new File([result], result.name, {type: result.type})
resolve(newFile);
});
}
三、Blob -> Base64
export function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = (e) => {
resolve(e.target.result);
};
// readAsDataURL
fileReader.readAsDataURL(blob);
fileReader.onerror = () => {
reject(new Error('文件流异常'));
};
});
}