富文本编辑器的内容导出html,并保留图片

发布于:2025-04-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

富文本编辑器的上传的图片默认转为base64,但是如果需要保存到数据库,base64的数据就太大了,所以一般都会长传到文件服务器,然会返回图片url。

但是当我们需要把富文本编辑器的内容导出为html时,因为图片时url,当浏览器离线浏览时就无法显示了,所以,在导出时,如果是图片,就把图片转为base64,这样即使在离线的情况下也能显示图片了。
在这里插入图片描述

package com.chen.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.jfinal.kit.PathKit;

import cn.hutool.core.util.IdUtil;

/**
* @author 作者 @Chenxc:
* 
*/
public class Export2HtmlUtil {
	
	private static final String localPath = PathKit.getWebRootPath()+File.separator+"genhtml";
	private static final String uploadPath = PathKit.getWebRootPath()+File.separator+"upload";
	
	/**
	**把html字符串转成文件
	*/
	public static File HtmlToFile(String html) {
		if(null == html) {
			return null;
		}
		String uuid = IdUtil.simpleUUID();
		String htmlFilePath = localPath+File.separator+uuid+".html";
		String convertedHtml;
		try {
			convertedHtml = convertHtmlImagesToBase64(html);
			Path path = Paths.get(htmlFilePath);
			Files.write(path, convertedHtml.getBytes("utf-8"));
			return path.toFile();
		} catch (IOException e) {
			 System.err.println("Failed to HtmlToFile: ");
             e.printStackTrace();
			 return null;
		}
	}
	
	
	
    private static String convertHtmlImagesToBase64(String html) throws IOException {
        Document doc = Jsoup.parse(html);
        Elements imgs = doc.select("img");

        for (Element img : imgs) {
            String imageUrl = img.attr("src");
            if (isRemoteUrl(imageUrl)) {
                try {
                    String base64Data = fetchImageAsBase64(imageUrl);
                    img.attr("src", base64Data);
                } catch (IOException e) {
                    System.err.println("Failed to process image: " + imageUrl);
                    e.printStackTrace();
                }
            }else if(isLocalUrl(imageUrl)){
            	try {
            		String substring = imageUrl.substring(imageUrl.lastIndexOf("/")+1);
            		String path = uploadPath+File.separator+substring;
                    String base64Data = convertLocalImgToBase64WithPrefix(path);
                    img.attr("src", base64Data);
                } catch (Exception e) {
                    System.err.println("Failed to process image: " + imageUrl);
                    e.printStackTrace();
                }
            }
        }

        return doc.outerHtml();
    }



    
    private static String convertLocalImgToBase64WithPrefix(String filePath) throws Exception {
        byte[] imageBytes = readFileBytes(filePath);
        String mimeType = Files.probeContentType(Paths.get(filePath));
        return "data:" + mimeType + ";base64," +
                Base64.getEncoder().encodeToString(imageBytes);
    }
    
    
    private static String fetchImageAsBase64(String imageUrl) throws IOException {
        URL url = new URL(imageUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);

        try (InputStream inputStream = connection.getInputStream();
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            if (connection.getResponseCode() != 200) {
                throw new IOException("HTTP error: " + connection.getResponseCode());
            }

            String contentType = connection.getContentType();
            if (contentType == null || !contentType.startsWith("image/")) {
                contentType = getContentTypeFromExtension(imageUrl);
            }

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            byte[] imageBytes = outputStream.toByteArray();
            String base64 = Base64.getEncoder().encodeToString(imageBytes);
            return "data:" + contentType + ";base64," + base64;
        } finally {
            connection.disconnect();
        }
    }

    private static String getContentTypeFromExtension(String imageUrl) {
        if (imageUrl.toLowerCase().endsWith(".png")) return "image/png";
        if (imageUrl.toLowerCase().endsWith(".jpg") || imageUrl.toLowerCase().endsWith(".jpeg")) return "image/jpeg";
        if (imageUrl.toLowerCase().endsWith(".gif")) return "image/gif";
        if (imageUrl.toLowerCase().endsWith(".webp")) return "image/webp";
        return "application/octet-stream";
    }
    
    private static byte[] readFileBytes(String filePath) throws Exception {
        Path path = Paths.get(filePath);
        return Files.readAllBytes(path);
    }
    
    private static boolean isRemoteUrl(String url) {
        return url.startsWith("http://") || url.startsWith("https://");
    }

    private static boolean isLocalUrl(String url) {
        return url.startsWith("/upload") || url.startsWith("upload");
    }
}