vue-html5-editor富文本编辑器抓取网络图片本地化

时间:2024-05-05 14:40:03

在vue中使用vue-html5-editor做的文章内容编辑器,至于怎么引用可另行百度,网络上有很多介绍;本文主要介绍如何在复制粘贴的时候跳过跨域限制和禁止外站的图片请求问题。

本文的方法比较笨拙,一起交流学习。

在研究使用vue-html5-editor的过程中,并没有发现对于复制粘贴过来图片的单独处理,倒是有一个insertImageUrl方法用来处理图片通过url粘贴过来的逻辑,不会重写该方法且该方法只针对通过图片功能上传的方式,因此放弃了。

后来实在没有办法了,决定在暴露出来的监听事件updateData方法中进行改造,思路如下:
1、监听文章内容变化,使用正则判断文章内容中是否有标签,并获取判断该标签中的src属性是否含有http或者https类型的图片链接;
2、提取出来图片的url链接;
3、调用后台接口,参数为url链接,通过后台接口访问图片链接并保存图片到自己的服务器,然后返回自己的服务器的图片url链接(这块我没有实现,我简单用base64做了测试);

前端代码:

async updateData(e = '') {
      var innerHTML = e.replace(/crossorigin="anonymous"/g,"");
      // 判断内容中是否有图片元素
      const imgRegex = /<img\s+[^>]*?src=(["'])(https?:\/\/[^\s'"]+)\1[^>]*>/g;
      var imageUrls = [];
      let match;
      while ((match = imgRegex.exec(innerHTML)) !== null) {
        // 要替换的url,调用后台接口,生成base64字符串
        var url = match[2];
        imageUrls.push(url);
        var result = await this.getHttpImgBase64(url);
        innerHTML = innerHTML.replace(url,result.data.ROOT.BODY.OUT_DATA);
      }
      this.content = innerHTML;
    },
    // 抓取网络图片,生成base64字符串
    getHttpImgBase64(url) {
      var data = new FormData();
      data.append('url',url);
      return getHttpImgBase64(data);
    },

其中return的getHttpImgBase64为调用后端接口的请求。

后端代码:

@ApiOperation(value = "抓取网络图片", notes = "用于适配编辑器,返回base64字符串")
	@PostMapping(value = "/getHttpImgBase64")
	public R<String> getHttpImgBase64(@RequestParam String url) {
		log.info("接收图片网络地址:" + url);
        String encodeToString = "";
        InputStream ins = null;
        try {
        	URL imgURL = new URL(url);//转换URL
        	HttpURLConnection urlConn = (HttpURLConnection) imgURL.openConnection();//构造连接
        	urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36");
        	urlConn.connect();
			if (urlConn.getResponseCode() == 200) {//返回的状态码是200 表示成功
			    ins = urlConn.getInputStream(); //获取输入流,从网站读取数据到 内存中
			    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
			    byte[] buffer = new byte[1024];  
			    int bytesRead;  
     
			    // 读取InputStream中的数据到ByteArrayOutputStream  
			    while ((bytesRead = ins.read(buffer)) != -1) {  
			        byteArrayOutputStream.write(buffer, 0, bytesRead);  
			    }  
     
			    // 获取ByteArrayOutputStream中的数据到byte[]  
			    byte[] fileInBytes = byteArrayOutputStream.toByteArray();  
     
			    // 使用Base64编码byte[]为字符串  
			    encodeToString = Base64.getEncoder().encodeToString(fileInBytes);
			    
				/**
				 * 1.Java使用BASE64Encoder 需要添加图片头("data:" + contentType + ";base64,"),
				 *   其中contentType是文件的内容格式。
				 * 2.Java中在使用BASE64Enconder().encode()会出现字符串换行问题,这是因为RFC 822中规定,
				 *   每72个字符中加一个换行符号,这样会造成在使用base64字符串时出现问题,
				 *   所以我们在使用时要先用replaceAll("[\\s*\t\n\r]", "")解决换行的问题。
				 */
			    encodeToString = "data:" + urlConn.getContentType() + ";base64," + encodeToString;
			    encodeToString = encodeToString.replaceAll("[\\s*\t\n\r]", "");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {  
            // 关闭InputStream  
            if (ins != null) {  
                try {  
                	ins.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
		return R.ok(encodeToString);
	}

本人基础知识不太扎实,如果有哪里需要优化的可以在评论区一起交流,另外欢迎补充返回url的代码。