一、功能概述
本方案实现将前端传递的base64格式图片转换为可访问的url链接,核心功能包含:
- base64数据有效性校验
- 图片压缩(转换webp格式+质量调整)
- exif方向信息自动校正
- 阿里云oss存储对接
- 完整的异常处理机制
二、核心实现代码
1.获取base64图片数据
首先,我们从json对象中获取base64编码的图片数据,并检查其是否为空或为空字符串。
string base64image = param.getstring("base64");
if (base64image == null || base64image.isempty()) {
throw new illegalargumentexception("base64 image data is missing");
}
2 .移除数据前缀
base64编码的图片数据通常包含一个前缀,例如 “data:image/png;base64,”。我们需要移除这个前缀以获取纯base64数据。
string[] parts = base64image.split(",");
if (parts.length != 2) {
throw new illegalargumentexception("invalid base64 image data");
}
byte[] imagebytes = base64.getdecoder().decode(parts[1]);
3.创建临时文件
将字节数组写入临时文件,以便后续处理。
file tempfile = file.createtempfile("tempimage", ".jpg");
try (fileoutputstream fos = new fileoutputstream(tempfile)) {
fos.write(imagebytes);
}4.转换图片格式
使用imageio和webpwriteparam将图片转换为webp格式,并进行压缩。
imagewriter writer = imageio.getimagewritersbymimetype("image/webp").next();
writer.setoutput(new fileimageoutputstream(newfile));
webpwriteparam writeparam = new webpwriteparam(writer.getlocale());
writeparam.setcompressionmode(webpwriteparam.mode_explicit);
writeparam.setcompressiontype(writeparam.getcompressiontypes()[0]);
writeparam.setcompressionquality(0.1f);
bufferedimage image = imageio.read(new fileinputstream(tempfile));
writer.write(null, new iioimage(image, null, null), writeparam);
writer.dispose();
5.调整图片方向
根据图片的exif信息调整图片方向(可选)。
metadata metadata = imagemetadatareader.readmetadata(tempfile);
exififd0directory exifdir = metadata.getfirstdirectoryoftype(exififd0directory.class);
if (exifdir != null && exifdir.containstag(exififd0directory.tag_orientation)) {
orientation = exifdir.getint(exififd0directory.tag_orientation);
}
switch (orientation) {
case 6: // 顺时针旋转90度
image = rotateimage(image, 90);
break;
case 3: // 旋转180度
image = rotateimage(image, 180);
break;
case 8: // 逆时针旋转90度
image = rotateimage(image, 270);
break;
}
6.上传到oss
使用osstemplate将转换后的图片上传到oss。
7… 返回文件url
上传完成后,返回文件的url地址。
三、关键技术点解析
1. base64数据处理
- 数据校验:通过split(“,”)分离数据头与有效数据
- 字节解码:使用java8+内置base64解码器
- 大小记录:记录原始图片大小用于监控
2. 图片压缩优化
| 参数 | 值 | 作用说明 |
|---|---|---|
| 压缩格式 | webp | 相比jpeg节省30%空间 |
| 压缩质量 | 0.1f | 质量与文件大小的平衡点 |
| 压缩模式 | explicit | 显式控制压缩参数 |
3. exif方向校正
ios等设备拍摄的照片可能包含方向标记,常见情况:
- 6:手机竖拍(需要顺时针旋转90°)
- 3:倒置拍摄(旋转180°)
- 8:逆时针90°拍摄(旋转270°)
4. oss上传优化
- 临时文件机制:避免内存溢出风险
- 自动清理:finally块确保删除临时文件
- 命名策略:时间戳+随机数保证唯一性
四、性能对比测试
对1920x1080的jpeg图片处理结果:
| 处理阶段 | 文件大小 | 耗时 |
|---|---|---|
| 原始图片 | 2.3mb | - |
| webp压缩后 | 680kb | 420ms |
| 质量调整+旋转 | 210kb | 520ms |
五、最佳实践建议
- 压缩质量调整:根据业务场景在0.1-0.3之间调整
- 异常监控:添加oss上传失败重试机制
- 内存优化:使用try-with-resources管理流
- 扩展方向:
- 添加cdn缓存头设置
- 对接图片审核服务
- 实现分布式文件存储
六、常见问题排查
q1 图片上传后方向仍然错误?
- 检查exif读取是否被其他程序修改
- 验证旋转算法与实际设备的匹配情况
q2 压缩后图片质量不理想?
- 调整setcompressionquality参数
- 改用有损+无损混合压缩模式
q3 oss链接无法访问?
- 检查bucket读写权限设置
- 验证oss endpoint配置
- 确认网络防火墙策略
七、完整代码示例
public string converturl(jsonobject param) {
// 从json对象中获取base64编码的图片数据
string base64image = param.getstring("base64");
//获取base64的大小
// 检查base64图片数据是否为空或为空字符串
if (base64image == null || base64image.isempty()) {
throw new illegalargumentexception("base64 image data is missing");
}
// log.info("base64image:{}",base64image);
// 移除数据前缀 "data:image/png;base64,"
string[] parts = base64image.split(",");
// 检查base64数据是否包含两部分(前缀和数据)
if (parts.length != 2) {
throw new illegalargumentexception("invalid base64 image data");
}
// 解码base64数据为字节数组
byte[] imagebytes = base64.getdecoder().decode(parts[1]);
int size=imagebytes.length/ 1024;
log.info("压缩前的图片大小为:"+size+"kb");
// 生成带有前缀 "pic" 和时间戳的文件名
string filename = "pic_" + system.currenttimemillis() + ".webp";
try {
// 将字节数组转换为inputstream
//对照片进行压缩 改成webp格式 再上传
try {
// 创建临时文件
file tempfile = file.createtempfile("tempimage", ".jpg");
file newfile = file.createtempfile("tempimage", ".webp");
// 将bytearrayinputstream的内容写入到临时文件中
try (fileoutputstream fos = new fileoutputstream(tempfile)) {
fos.write(imagebytes);
}
// 使用临时文件创建fileimageoutputstream
imagewriter writer = imageio.getimagewritersbymimetype("image/webp").next();
writer.setoutput(new fileimageoutputstream(newfile));
webpwriteparam writeparam = new webpwriteparam(writer.getlocale());
writeparam.setcompressionmode(webpwriteparam.mode_explicit);
writeparam.setcompressiontype(writeparam.getcompressiontypes()[0]);
writeparam.setcompressionquality(0.1f);
//imageio 读取 tempfile
inputstream inputstream = new fileinputstream(tempfile);
//判断图片方向
bufferedimage image = imageio.read(inputstream);
int orientation = 1;
try {
metadata metadata = imagemetadatareader.readmetadata(tempfile);
exififd0directory exifdir = metadata.getfirstdirectoryoftype(exififd0directory.class);
if (exifdir != null && exifdir.containstag(exififd0directory.tag_orientation)) {
orientation = exifdir.getint(exififd0directory.tag_orientation);
}
log.info("图片方向为:{}",orientation);
// 根据方向调整图片(可选)
switch (orientation) {
case 6: // 顺时针旋转90度
image = rotateimage(image, 90);
break;
case 3: // 旋转180度
image = rotateimage(image, 180);
break;
case 8: // 逆时针旋转90度
image = rotateimage(image, 270);
break;
// 其他情况保持原样
}
} catch (exception e) {
log.warn("读取exif信息失败", e);
}
if (image == null) {
throw new illegalargumentexception("invalid image data");
}
writer.write(null, new iioimage(image, null, null), writeparam);
writer.dispose();
// 使用osstemplate将文件上传到oss
osstemplate.putobject("xxxxx", filename, new fileinputstream(newfile));
//获取临时文件大小
int filesize= (int) (newfile.length()/1024);
log.info("压缩后的图片大小为:"+filesize+"kb");
// 删除临时文件
tempfile.delete();
newfile.delete();
} catch (ioexception e) {
log.error("error occurred while compressing and uploading image", e);
throw new runtimeexception("failed to compress and upload image", e);
}
// 返回文件的url地址
return osstemplate.getobjecturl("xxxxx", filename);
} catch (exception e) {
log.error("error occurred while converting base64 image to url", e);
throw new runtimeexception("failed to convert base64 image to url", e);
}
}
// 辅助方法:旋转图片
private static bufferedimage rotateimage(bufferedimage image, int degrees) {
affinetransform transform = new affinetransform();
transform.rotate(math.toradians(degrees), image.getwidth()/2, image.getheight()/2);
affinetransformop op = new affinetransformop(transform, affinetransformop.type_bilinear);
return op.filter(image, null);
}
到此这篇关于java实现base64图片转url的完整方案的文章就介绍到这了,更多相关java base64图片转url内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论