图片压缩优化结合Base64存储的系统改进方案
需要帮助用户解决图片压缩优化结合Base64存储的问题。用户之前已经提到他们目前将图片以Base64格式存储在数据库中,导致接口传输数据过大,加载时间长达3秒。他们现在想通过图片压缩来优化系统,但不采用WebP格式转换。我需要详细思考如何在不改变存储格式的情况下,通过压缩和其他优化手段来减少数据量,提升性能。

<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.20</version>
</dependency>
第一种:原始图片通过流的形式获取后,再进行压缩
解决方式:使用Thumbnailator进行压缩
大致代码思路:在保存为Base64前最大限度减小图片体积。这种方式通过获取原始图片后,然后进行压缩形成Base64位的图片编码
// 使用Thumbnailator进行压缩(Java示例)
public String compressAndConvertToBase64(MultipartFile file) throws IOException {
// 压缩参数
double quality = 0.7; // 质量压缩到70%
int maxWidth = 1920; // 限制最大宽度
// 压缩处理
BufferedImage compressedImage = Thumbnails.of(file.getInputStream())
.width(maxWidth)
.outputQuality(quality)
.asBufferedImage();
// 转为Base64
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(compressedImage, "jpg", baos);
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
如果采用压缩比70%的方式进行压缩,则压缩比可以对照如下
| 原图参数 | 压缩前大小 | 压缩后大小 | Base64数据量减少 |
|---|---|---|---|
| 4000x3000 PNG(5MB) | 5MB | 1.2MB | 5MB → 1.6MB |
| 1920x1080 JPG(2MB) | 2MB | 0.6MB | 2.6MB → 0.8MB |
接口启用:GZIP压缩优化
# Spring Boot配置(application.yml)
server:
compression:
enabled: true
mime-types: text/html,text/css,text/javascript,application/json,image/svg+xml
min-response-size: 1024
第二种:如果图片已经是Base64格式,则我们可以通过解码方式再进行压缩
代码思路:
public String recompressBase64(String originalBase64) throws IOException {
// 去除Base64头信息(如"data:image/jpeg;base64,")
String pureBase64 = originalBase64.split(",")[1];
// 解码为字节数组
byte[] imageBytes = Base64.getDecoder().decode(pureBase64);
// 使用Thumbnailator压缩
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Thumbnails.of(new ByteArrayInputStream(imageBytes))
.scale(1)
.outputQuality(0.7)
.outputFormat("jpg")
.toOutputStream(outputStream);
// 重新编码为Base64
return "data:image/jpeg;base64," +
Base64.getEncoder().encodeToString(outputStream.toByteArray());
}
关键参数调优:
| 参数 | 推荐值 | 说明 |
|---|---|---|
outputQuality |
0.6-0.8 | 质量压缩比(1为无损) |
scale |
按需调整 | 缩放比例(0.5=50%尺寸) |
outputFormat |
jpg/png | 输出格式(jpg压缩率更高) |
| 处理阶段 | 原始方案(无压缩) | 前端预压缩 | 后端二次压缩 | 混合方案 |
|---|---|---|---|---|
| 传输数据量 | 13MB | 2.6MB | 13MB | 2.6MB |
| 服务器CPU消耗 | 低 | 低 | 高 | 中 |
| 客户端处理时间 | 0 | 1.2秒 | 0 | 0.8秒 |
| 最终存储体积 | 13MB | 2.6MB | 3.2MB | 1.8MB |
针对Base64图片编码进行压缩,我们优化后的代码,包含内存安全管理和尺寸限制。大家可以参考如下代码
public String recompressBase64(String originalBase64) throws IOException {
// 分离Base64头信息和数据部分
String[] parts = originalBase64.split(",");
if (parts.length < 2) {
throw new IllegalArgumentException("无效的Base64格式");
}
String mimeType = parts[0].split(";")[0].replace("data:", "");
String pureBase64 = parts[1];
// 解码为字节数组
byte[] imageBytes = Base64.getDecoder().decode(pureBase64);
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 读取原始图片信息
BufferedImage originalImage = ImageIO.read(inputStream);
if (originalImage == null) {
throw new IOException("无法解码图片数据");
}
// 新增像素限制检查 ---------------------------------------------------
int maxPixels = 1920 * 1080; // 约200万像素
long actualPixels = (long) originalImage.getWidth() * originalImage.getHeight();
if (actualPixels > maxPixels) {
throw new IOException("图片尺寸超过限制(最大允许1920x1080像素)");
}
// 自动旋转处理(修复手机图片方向问题)
Thumbnails.Builder<BufferedImage> builder = Thumbnails.of(originalImage)
.outputFormat(getOutputFormat(mimeType)) // 保持原始格式
.outputQuality(0.7);
// 应用尺寸限制(保持宽高比)
int originalWidth = originalImage.getWidth();
if (originalWidth > 1920) {
builder.width(1920);
} else {
builder.scale(1.0); // 保持原始尺寸
}
// 处理透明背景(如果是PNG转换为JPG)
if ("image/png".equalsIgnoreCase(mimeType) && originalImage.getTransparency() != Transparency.OPAQUE) {
builder.imageType(BufferedImage.TYPE_INT_RGB); // 转换为不透明格式
}
// 执行压缩并获取结果
builder.toOutputStream(outputStream);
// 重新编码为Base64
byte[] compressedBytes = outputStream.toByteArray();
return String.format("data:%s;base64,%s",
getMimeTypeWithFormat(mimeType),
Base64.getEncoder().encodeToString(compressedBytes));
}
}
// 获取输出格式
private String getOutputFormat(String mimeType) {
return switch (mimeType.toLowerCase()) {
case "image/png" -> "png";
case "image/bmp" -> "bmp";
case "image/gif" -> "gif";
default -> "jpg"; // 默认转为JPG
};
}
// 处理MIME类型
private String getMimeTypeWithFormat(String originalMimeType) {
return originalMimeType.startsWith("image/") ? originalMimeType : "image/jpeg";
}
优化说明
- 位置选择:在读取图片后立即检查,避免后续处理无效的大图
- 溢出防护:使用
(long)强制转换防止int溢出 - 错误信息:明确提示允许的最大尺寸
- 逻辑顺序:先检查尺寸 → 再处理旋转和压缩
图片压缩优化结合Base64存储的系统改进方案的更多相关文章
- Vue directive自定义指令+canvas实现H5图片压缩上传-Base64格式
前言 最近优化项目-手机拍照图片太大,回显速度比较慢,使用了vue的自定义指令实现H5压缩上传base64格式的图片 canvas自定义指令 Vue.directive("canvas&qu ...
- Android性能优化之图片压缩优化
1 分类Android图片压缩结合多种压缩方式,常用的有尺寸压缩.质量压缩.采样率压缩以及通过JNI调用libjpeg库来进行压缩. 参考此方法:Android-BitherCompress 备注:对 ...
- 将图片压缩后转Base64函数
function CutImgToBase(fn: string): string; // 压缩图片只能压缩bmp:将jpg转换成bmp再压缩 var m1: TMemoryStream; m2: T ...
- 图片压缩优化kraken
https://kraken.io/web-interface 测试过,可以节省10%左右的大小,图片清晰度不受影响.
- png图片压缩优化
1.2 软件环境 软件名称:Opting下载地址: http://optipng.sourceforge.net/ 安装版本:0.7.5安装位置:/apps/svr/opting 安装可能遇到的问题: ...
- 图片文件转换成Base64编码实现ajax提交图片
//上传头像图片 function uploadHead(imgPath) { console.log("imgPath = " + imgPath); var image = n ...
- 石火电光追风逐日|前端优化之次时代图片压缩格式WebP的项目级躬身实践(Python3 PIL+Nginx)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_190 我们知道,在前端界有一个共识:速度就是生命,带宽就是金钱.怎样将页面加载速度有效提升是无数前端工程师无时不刻在思考的课题,目 ...
- 性能优化——Android图片压缩与优化的几种方式
图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等1.设置图片格式Android目前常用的图片格式有png,jpeg和webp,png:无损压缩图片 ...
- Android 图片内存优化与图片压缩
1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource. BitmapFactory.decodeResource 来设置一张大图,因为这些方法在完成 ...
- php分10个不同等级压缩优化图片
今天找到一个php写的压缩图片程序,可以分10个等级(0-9)来压缩,0等级时压缩比率不是很大,图片不会失真:随着压缩等级不断增大,图片会变得越来越不清晰,通常压缩后图片大小可以减少到原来的50%,压 ...
随机推荐
- GROOVY 运行插件
如果想要在vscode里面运行groovy脚本,请先安装code runner插件
- MySQL EXISTS与IN用法对比分析
在 MySQL 中,EXISTS 和 IN 都用于子查询中根据另一个查询的结果来过滤主查询的记录,但它们的工作原理.效率和应用场景有显著区别.理解这些差异对于编写高效的 SQL 至关重要. 一.基本用 ...
- 万字带你深度了解MQ消息队列
MQ 消息队列 **首先我们人的精力是有限的,从投入产出来说,深入学习一种消息队列就够了,因为消息队列的使用都是相通的,只要你掌握了其中一种消息队列,你就可以说你会消息队列了,这就如同你无论掌握Jav ...
- iframe里面获取父级页面URL参数
getParam: function (name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'); ...
- VUE+WebRTC实现音视频直播
1 功能简介 本文将介绍如何快速使用 Vue 实现一个简单的实时音视频通话. 相关概念解释: ZEGO Express SDK:由 ZEGO 提供的实时音视频 SDK,能够为开发者提供便捷接入.高清流 ...
- AI 加持实时互动|ZegoAvatar 面部表情随动技术解析
01 AI"卷" 进实时互动 2021 年,元宇宙概念席卷全球,国内各大厂加速赛道布局,通过元宇宙为不同的应用场景的相关内容生态进行赋能.针对 "身份".&qu ...
- PVE虚拟机迁移仅需四步(独立主机)
需求:我有很多台PVE主机,他们都是独立部署的(不共享存储),因为资源分配问题,需要将一台PVE主机上的部分虚拟机迁移至另一台PVE主机 操作过程如下,均在PVE平台web页面即可进行,仅需四步. 1 ...
- 8寸平板iEnglish4刷机折腾记录
0 平板介绍 逛海鲜市场的时候,偶然发现了一款平板:iEnglish4,型号为9011,处理器MT6739,存储为2+16G,屏幕为8寸1280*800,4000mah电池,Type-C接口,整机尺寸 ...
- 产品动态|支持 RTMP 协议推流至 TRTC
https://cloud.tencent.com/developer/article/1931516
- 煤炭行业网络测试方案——RFC2544测试、网络监测、平台-基站-终端测试、安全测试
1.网络测试方案 1.1网络测试 虽然网络设备部署之前均已取得安标证书,但是由于矿区网络部署环境比较恶劣,尤其是综合布线系统完全暴露在极端条件下,为确保整体网络质量达到业务运行需求,在网络建设完成 ...