将html字符串中的base64图片转换成file并上传

目的
  • 解决富文本编辑器中复制粘贴的图片 base64 字符串过长导致无法存储到数据库的问题
思路
  • 通过正则 获取html字符串中里面的所有图片 base64 数组 然后每个图片base64 转成file
  • 使用上传文件的函数 上传到服务器上.
  • 将上传后获取到的图片访问url 替换成 数据里面的 img 的 src.
代码
/**
 * 将html中的 图片base64 通过调上传文件接口转换成图片url
 * */

/**
上传文件
**/
export function uploadFile(params) {
	let url = `/upload`; // 
	const formData = new FormData();
	for (let item in params) {
		formData.append(item, params[item]);
	}
	return fetch(url, {
		method: 'POST',
		headers: {
			Accept: '*/*',
		},
		body: formData,
	})
		.then((res) => {
			return res.json();
		})
		.then((responseData) => {
			if(responseData && typeof responseData === 'object' && responseData.url){
				return responseData;
			}
			if (responseData && responseData.data) {
				return responseData.data;
			} else {
				throw new Error('文件上传失败');
			}
		})
		.catch(() => {
			throw new Error('上传文件失败');
		});
}

// base64转url
export default function base64ImgToUrl(htmlContent = ''){
	return new Promise((resolve, reject) => {
		let splitContent = getImages(htmlContent);  // 获取所有的图片 的 base64 src
		let res = [];
		for(let item of splitContent){
			if(item && item.includes(';base64,')){
				const file = {
					base64: item,
				};
				file.file = base64toFile(item, new Date().getTime()); // 将图片转换成file
				res.push(file);
			}
		} // 任务列表

		async function DoTaskByForOf() {
			for (let item of res) { // 按顺序执行
					const fileResponse = await uploadFile({file:item.file}); // 上传文件到服务器
					if(fileResponse && fileResponse.url){
						item.url = fileResponse.url;
					}
			}
			return res;
		}
		DoTaskByForOf().then((r) => {
			resolve(r);
		}); // 按顺序执行
	})
}

/**
 * 使用正则表达式从HTML字符串中获取所有图像src
 * */
export function getImages(html) {
	const regExp = /]+src=['"]([^'"]+)['"]+/g;
	const result = [];
	let temp;
	while ((temp = regExp.exec(html)) != null) {
		result.push(temp[1]);
	}
	return result;
}


/**
 * 把base64图片转为文件对象
 * 第一个参数dataUrl是一个base64的字符串。第二个参数是文件名可以随意命名
 */
export function base64toFile(dataUrl = '', filename = 'file') {
	let arr = dataUrl.split(',');
	let mime = arr[0].match(/:(.*?);/)[1];
	// suffix是该文件的后缀
	let suffix = mime.split('/')[1];
	// atob 对经过 base-64 编码的字符串进行解码
	let bstr = atob(arr[1]);
	// n 是解码后的长度
	let n = bstr.length;
	// Uint8Array 数组类型表示一个 8 位无符号整型数组 初始值都是 数子0
	let u8arr = new Uint8Array(n);
	// charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数
	while (n--) {
		u8arr[n] = bstr.charCodeAt(n);
	}
	// new File返回File对象 第一个参数是 ArraryBuffer 或 Bolb 或Arrary 第二个参数是文件名
	// 第三个参数是 要放到文件中的内容的 MIME 类型
	return new File([u8arr], `${filename}.${suffix}`, {
		type: mime,
	});
}

你可能感兴趣的:(html,前端)