---------------------------------- BEGIN ---------------------------------
背景:
專案需要,不同伺服器之間圖片截圖互傳,JS new Image() 涉及到跨域問題,於安全考慮,禁用伺服器跨域,於是週轉瞭如下解決方案。
具體邏輯:
java 後臺 根據圖片SRC獲取圖片Base64編碼供前臺顯示, 前臺 JS 操作(裁剪、截圖,前面文章有具體方法 JS 自定義 截圖、裁剪), 完成後將Base64字串傳到後臺,後臺解碼生成MultipartFile ...
1、先上 公共的檔案處理類 WebFileUtils
package com.aaa.bbb.ccc.ddd.helper;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.util.Base64;
/**
* @Function : 圖片處理幫助類 - 把URL裡的圖片匯入到本地 - 將IMG的SRC地址轉為File - base64編碼圖片轉 MultipartFile
* @Author & @Date : lynn_ - 2018年06月15日
*/
@Service("webFileUtils")
public class WebFileUtils {
/**
* 臨時檔案位置
*/
private static String tempFilePath = "";
/**
* 根據url拿取file
*
* @param url
* @param suffix - 檔案字尾名
*/
public static File createFileByUrl(String url, String suffix) {
byte[] byteFile = getImageFromNetByUrl(url);
if (byteFile != null) {
File file = getFileFromBytes(byteFile, suffix);
return file;
} else {
System.out.println("生成檔案失敗!");
return null;
}
}
/**
* @Function: 建立臨時檔案
* @param byteFile
* @param suffix
*/
private static File getFileFromBytes(byte[] byteFile, String suffix) {
BufferedOutputStream stream = null;
File file = null;
try {
//注意這裡的臨時檔案 需要自行刪除
file = File.createTempFile("pattern", "." + suffix);
tempFilePath = file.getCanonicalPath();
System.out.println("臨時檔案位置:" + tempFilePath);
FileOutputStream fstream = new FileOutputStream(file);
stream = new BufferedOutputStream(fstream);
stream.write(byteFile);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return file;
}
/**
* @Function: 根據地址獲得資料的位元組流 - GET請求
* @param url - 網路連線地址
*/
private static byte[] getImageFromNetByUrl(String strUrl) {
try {
URL url = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
// 通過輸入流獲取圖片資料
InputStream inStream = conn.getInputStream();
// 得到圖片的二進位制資料
byte[] btImg = readInputStream(inStream);
return btImg;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Function: 從輸入流中獲取資料
* @param inStream - 輸入流
* @throws IOException
*/
private static byte[] readInputStream(InputStream inStream) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
/**
* @Function: 刪除臨時檔案
*/
public static Boolean deleteFile() {
boolean flag = false;
File file = new File(tempFilePath);
// 路徑為檔案且不為空則進行刪除
if (file.isFile() && file.exists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* @Function: base64編碼圖片轉 MultipartFile
* 注意 轉碼時 需要把data:image/png;base64,這個字首給去掉
*/
public static MultipartFile base64ToMultipart(String base64) {
if (base64.indexOf(",") > -1) {
String[] baseStrs = base64.split(",");
if (null != baseStrs && baseStrs.length > 0) {
byte[] b = new byte[0];
b = Base64.decodeFast(baseStrs[1]);
for (int i = 0; i < b.length; ++i) {
// 調整異常資料
if (b[i] < 0) {
b[i] += 256;
}
}
return new BASE64DecodedMultipartFile(b, baseStrs[0]);
}
}
return null;
}
/**
* @Function: 將一張網路圖片轉化成Base64字串
* @param imgSrc - 網路圖片資源位置
*/
public static String getImageBase64StrFromUrl(String imgSrc){
URL url = null;
InputStream is = null;
ByteArrayOutputStream outStream = null;
HttpURLConnection httpUrl = null;
try{
url = new URL(imgSrc);
httpUrl = (HttpURLConnection) url.openConnection();
httpUrl.setRequestMethod("GET");
httpUrl.setConnectTimeout(5 * 1000);
httpUrl.connect();
httpUrl.getInputStream();
is = httpUrl.getInputStream();
outStream = new ByteArrayOutputStream();
//建立一個Buffer字串
byte[] buffer = new byte[1024];
//每次讀取的字串長度,如果為-1,代表全部讀取完畢
int len = 0;
//使用一個輸入流從buffer裡把資料讀取出來
while( (len=is.read(buffer)) != -1 ){
//用輸出流往buffer裡寫入資料,中間引數代表從哪個位置開始讀,len代表讀取的長度
outStream.write(buffer, 0, len);
}
// 對位元組陣列Base64編碼
return java.util.Base64.getEncoder().encodeToString(outStream.toByteArray());
}catch (Exception e) {
e.printStackTrace();
}finally{
if(is != null) {
try {is.close(); } catch (IOException e) {e.printStackTrace(); }
}
if(outStream != null) {
try {outStream.close();} catch (IOException e) {e.printStackTrace();}
}
if(httpUrl != null){ httpUrl.disconnect();}
}
return imgSrc;
}
複製程式碼
}
2、自定義 BASE64DecodedMultipartFile 類
package com.aaa.bbb.ccc.ddd.helper;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.web.multipart.MultipartFile;
/**
* @Function : 自定義 BASE64DecodedMultipartFile 類
* @Author & @Date : lynn_ - 2018年06月15日
*/
public class BASE64DecodedMultipartFile implements MultipartFile {
private final byte[] imgContent;
private final String header;
public BASE64DecodedMultipartFile(byte[] imgContent, String header) {
this.imgContent = imgContent;
this.header = header.split(";")[0];
}
@Override
public String getName() {
return System.currentTimeMillis() + "." + header.split("/")[1];
}
@Override
public String getOriginalFilename() {
return System.currentTimeMillis() + "." + header.split("/")[1];
}
@Override
public String getContentType() {
return header.split(":")[1];
}
@Override
public boolean isEmpty() {
return imgContent == null || imgContent.length == 0;
}
@Override
public long getSize() {
return imgContent.length;
}
@Override
public byte[] getBytes() throws IOException {
return imgContent;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(imgContent);
}
@SuppressWarnings("resource")
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
new FileOutputStream(dest).write(imgContent);
}
}
複製程式碼
3、下面開始 呼叫測試
//根據圖片SRC獲取圖片Base64編碼
String base64Str = WebFileUtils.getImageBase64StrFromUrl(imgSrc);
System.out.println(base64Str);
//圖片base64編碼轉 MultipartFile
MultipartFile mf = WebFileUtils.base64ToMultipart(src_base64Str);
//IMG的SRC地址轉為File; File轉換成MutipartFile
File file = WebFileUtils.createFileByUrl(imgsrc, "png");
FileInputStream inputStream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(imgName, imgOriginalFileName, contentType, inputStream);
複製程式碼
---------------------------------- END ---------------------------------