Spring Boot中无损压缩图片到KB级 解决邮件内嵌图渲染慢问题
邮件内嵌图片压缩渲染优化问题
问题背景
- Spring Boot项目中渲染带内嵌图片的邮件时,编辑器(Iframe)无法识别
CID:***格式的图片链接 - 现有方案将CID替换为base64编码的图片内容,可正常渲染,但单张10Mb或5-10张图片时渲染耗时可达10秒(邮件内容存储在MongoDB中)
- 需求:实现图片压缩+尺寸调整,适配编辑器展示,降低渲染耗时
原有CID替换实现代码
private String processInlineHtmlImages(String htmlContent, MimeMessageParser parser, String messageId) throws IOException { Collection<String> contentIds = parser.getContentIds(); if (!CollectionUtils.isEmpty(contentIds)) { for (Iterator<String> contentId = contentIds.iterator(); contentId.hasNext();) { String cid = contentId.next(); String imageContentId = "cid:" + cid; if (htmlContent.contains(imageContentId)) { DataSource contentIdbyteArray = parser.findAttachmentByCid(cid); String imageType = contentIdbyteArray.getContentType() != null ? contentIdbyteArray.getContentType() : "jpg"; if (contentIdbyteArray != null) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { IOUtils.copy(contentIdbyteArray.getInputStream(), outputStream); } catch (IOException e) { logger.error("CCM-MessageID: {} exception while processing inline image", messageId); } byte[] bytes = outputStream.toByteArray(); // Resize the image if its greater then 1Mb if (bytes.length > 1048576) { // Compress code should be here if size of bytes more than 1Mb } StringBuilder imgSrc = new StringBuilder(); imgSrc.append("data:image/" + imageType + ";base64,"); imgSrc.append(Base64.getEncoder().encodeToString(bytes)); // This will replace the html inline image cid to its bytes htmlContent = htmlContent.replaceAll(imageContentId, imgSrc.toString()); } } } return htmlContent; } return null; }
优化方案
工具选型
使用Java生态常用的Thumbnails图片处理库,原生支持等比例尺寸调整、画质压缩,API简单易用,适配JPG、PNG等主流图片格式。
压缩逻辑实现
在原有代码的压缩逻辑预留位置,加入如下代码即可实现尺寸适配+压缩:
// 导入对应类:import net.coobird.thumbnailator.Thumbnails; ByteArrayInputStream compressInput = new ByteArrayInputStream(bytes); ByteArrayOutputStream compressOutput = new ByteArrayOutputStream(); Thumbnails.of(compressInput) // 按编辑器最大展示宽度等比缩放,高度自适应,避免图片变形 .width(1200) // 压缩质量设置为0.8,可根据实际清晰度需求调整,取值范围0.0-1.0 .outputQuality(0.8f) // 保持原有图片格式 .outputFormat(imageType) .toOutputStream(compressOutput); // 替换为压缩后的字节数组 bytes = compressOutput.toByteArray();
优化注意点
- 若使用PNG格式带透明通道的图片,不要强制转换为JPG格式,避免透明背景变为黑色
- 可根据业务需求调整最大宽度和压缩质量参数,平衡清晰度和文件体积
- 若对压缩后体积有严格要求,可增加循环判断逻辑,调整压缩参数直到体积符合阈值要求
内容的提问来源于stack exchange,提问作者Shrey Soni
相关产品推荐
相关产品推荐

