上週使用 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;
}