2018-06-15: Java 將網路圖片SRC轉換為Base64, Base64轉 MultipartFile

lynn_發表於2018-06-15

---------------------------------- 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 ---------------------------------

相關文章