上周使用 base64 上传图片到OSS中的时候,发现保存的图片出现显示马赛克和图片破损打不开的情况。找了很久也没有出现问题,今天在找答案的时候,偶然间发现有个博主分享的内容完美的解决了我的问题(这里特别感谢这位博主的分享),所以特此记录一下,希望能够帮助遇到同样问题却又苦苦挣扎的朋友们。
关于 base64编码 保存的图片无法正常显示的问题,需要注意两点:
1)上传使用的 base64编码 只需要 “data:image/png;base64,”(这个是指图片的格式,也有可能是“data:image/jpeg;base64,”等)之后的字符串,所以一定要去掉这个前缀。
备注:截取的时候可以使用 base64字符串.substring(base64字符串.indexOf(",") + 1) 方法;
2)如果第一点已经确认写的没问题,但是图片仍然显示有问题(我就是这个问题),那么可以继续往下看:
Postman/Ajax (我是使用Postman的时候出现的问题) 在传 base64编码 的时候,会把 base64编码 中的 "+" 号换成空格,所以需要先将base64中的空格转换回来,再进行保存操作!
下面是使用 base64编码 上传的工具类:
public static String getBase64ToImg(String userPhoto,String userId){
Date date = new Date();
SimpleDateFormat sft = new SimpleDateFormat("yyyy-MM-dd");
String newUserPhoto = null;
// 判断base64编码是否为空
if(StringUtils.notNull(userPhoto)){ // base64编码不为空
// 1)截取获取到的base64编码,去掉前缀"data:image/png;base64," || "data:image/jpeg;base64,",只取base64编码
// 2)需要将 base64编码 中的空格转换成 + 号
userPhoto = userPhoto.substring(userPhoto.indexOf(",") + 1).replaceAll(" ", "+");
try {
newUserPhoto = "images/" + sft.format(date).toString() + "/" + userId + ".png";
//Base64解码
BASE64Decoder decoder = new BASE64Decoder();
byte[] photoBase64 = decoder.decodeBuffer(userPhoto);
for(int i=0;i<photoBase64.length;++i)
{
if(photoBase64[i]<0)
{//调整异常数据
photoBase64[i]+=256;
}
}
/* 保存到本地 如果要保存到OSS中,这个块可以不用写 begin*/
// 创建当前日期的文件件
File file = new File("images/" + sft.format(date).toString() + "/");
file.mkdirs();
newUserPhoto = "images/" + sft.format(date).toString() + "/" + userId +".png"; //新生成的图片
OutputStream out = new FileOutputStream(newUserPhoto);
out.write(photoBase64);
out.flush();
out.close();
/* 保存到本地 end*/
/* 上传至OSS 如果需要将图片上传至OSS,只需要在 Base64解码 之后,直接调用OSS的SDK即可,不需要再保存到本地 begin*/
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-beijing.aliyuncs.com";
// 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建。
String accessKeyId = "xxxxxxx";
String accessKeySecret = "xxxxxxxx";
String bucketName = "images";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeySecret);
// 上传Byte数组。
ossClient.putObject(bucketName, newUserPhoto, new ByteArrayInputStream(photoBase64));
// 关闭OSSClient。
ossClient.shutdown();
/* 上传至OSS 如果需要将图片上传至OSS,只需要在 Base64解码 之后,直接调用OSS的SDK即可,不需要再保存到本地 end*/
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return newUserPhoto;
}