网络日志

解析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 的地址都处理完毕了。