解析html中的图片地址并传到自己服务器
处理需求:当从其他编辑器粘贴过来内容且包含图片时,需要把图片传到自己的服务器。记录一下解决方案以及踩到的坑。
解析 html
从剪切板或者接口中拿到的 html 串,需要解析其中涉及到的所有图片,此处我们使用正则表达式。
let htmlContent = '拿到的html串'
const { content, imgs } = this.getHtmlAndImgs(htmlContent)
htmlContent = content
imgs.forEach(async item => {
const formData = await this.imgUrlToFomdata(item.url)
this.uploadToServer(formData, item.id)
})
getHtmlAndImgs (htmlContent) {
const imgs = []
htmlContent = htmlContent.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, (match, capture) => {
// match 匹配的整体值(该处是形似<img src="" />的内容)
// capture 正则匹配到的值(该处是形似 http://www.xxxxx.com 的图片链接地址)
// 排除属于自己的服务器地址
if (capture.includes('www.xxxxx.com')) {
return match
}
// this.count 初始值为0,imgs存储图片 id 和链接,方便通过操作dom来替换内容
const item = {
url: capture,
id: 'pasteImg' + (++this.count)
}
imgs.push(item)
// 将 html 中的图片地址替换,同时给每一张图片赋值 id
return match.replace(capture, '加载中的图片地址').replace(/<img/, `<img id="${item.id}"`)
});
return {
content: htmlContent,
imgs
}
}
将图片地址转为 formdata 对象
这个地方有个需要注意的点是,fetch 会有同源跨域的问题,就算mode
设置为no-cors
也是无效的,如果请求的图片服务器做了限制,就需要去服务器设置nginx
。
不使用canvas
转 base64 是因为无法处理动图。
imgUrlToFomdata (url) {
return new Promise((resolve, reject) => {
fetch(url)
.then(respone => respone.blob())
.then(blob => {
const formData = new FormData();
const { type } = blob
const imgSuffix = type.substring(6)
// 不设置名字和后缀,接口会报错401,具体看后端接口代码
const fileName = `${new Date().getTime()}.${imgSuffix}`
const file = new File([blob], fileName, { type });
formData.append('file', file, fileName);
resolve(formData)
})
.catch(error => {
reject(error)
});
})
}
将图片上传到服务器
将图片转换后的 formdata 二进制文件上传到服务器,并通过 id 重新设置图片地址为自己服务器的地址。
async uploadToServer (formData, id) {
const res = await this.$api.upload.blogImgUpload(formData);
const { code, data, message } = res.data;
if (code === 200) {
// 我的编辑器使用的是tinymce,获取编辑器内容的 dom 元素需要通过 activeEditor 获取
tinymce.activeEditor.getBody().querySelector(`#${id}`).src = data;
} else {
this.$message.error(message);
}
}
至此,处理 html 并设置 img 的地址都处理完毕了。
转载自:https://segmentfault.com/a/1190000042295695