共计 1738 个字符,预计需要花费 5 分钟才能阅读完成。
解决需要:当从其余编辑器粘贴过去内容且蕴含图片时,须要把图片传到本人的服务器。记录一下解决方案以及踩到的坑。
解析 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 的地址都处理完毕了。
正文完