項目有一個需求是:
從網上下載圖片,並用BASE64 轉為字符串發送給別人。
從網上看了很多,我最終主要是 用
sun.misc.BASE64Decoder 和 sun.misc.BASE64Encoder 實現
代碼如下:
package ins.platform.web.utils; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; /** * * @Description: 下載圖片 * @author: * @date: 2018年1月5日 上午11:31:05 * @version V1.0 * @Copyright: 2018 www.newtouch.cn . All rights reserved. * */ public class PictureDownLoadUtil { private static final Logger LOGGER = LoggerFactory.getLogger(PictureDownLoadUtil.class); private static final int PROTECTED_LENGTH = 1024 * 1024;// 輸入流保護 1M public static String downLoad(String strUrl, Boolean isProxy, String host, String port) { if (isProxy) { setProxy(host, port); } URL url = null; try { url = new URL(strUrl); } catch (MalformedURLException e2) { LOGGER.error("下載圖片異常,新建URL失敗"); return ""; } InputStream is = null; try { is = url.openStream(); return readInfoStreamToBytes(is); } catch (IOException e1) { LOGGER.error("下載圖片異常"); return ""; } } public static void setProxy(String host, String port) { System.setProperty("proxySet", "true"); System.setProperty("proxyHost", host); System.setProperty("proxyPort", port); } public static void main(String[] args) { String str = "http://7xrnr1.com1.z0.glb.clouddn.com/090406.png"; String picStr = PictureDownLoadUtil.downLoad(str, true, "", ""); GenerateImage(picStr); System.out.print(picStr); } public static boolean GenerateImage(String imgStr) { // 對字節數組字符串進行Base64解碼並生成圖片 if (imgStr == null) // 圖像數據為空 return false; BASE64Decoder decoder = new BASE64Decoder(); try { // Base64解碼 byte[] b = decoder.decodeBuffer(imgStr); for (int i = 0; i < b.length; ++i) { if (b[i] < 0) {// 調整異常數據 b[i] += 256; } } // 生成jpeg圖片 String imgFilePath = "d://qq.jpg";// 新生成的圖片 OutputStream out = new FileOutputStream(imgFilePath); out.write(b); out.flush(); out.close(); return true; } catch (Exception e) { return false; } } public static String readInfoStreamToBytes(InputStream is) { if (is == null) { LOGGER.error("輸入流為null"); return null; } // 字節數組 byte[] bCache = new byte[2048]; int readSize = 0;// 每次讀取的字節長度 int totalSize = 0;// 總字節長度 ByteArrayOutputStream infoStream = new ByteArrayOutputStream(); try { // 一次性讀取2048字節 while ((readSize = is.read(bCache)) > 0) { totalSize += readSize; if (totalSize > PROTECTED_LENGTH) { LOGGER.error("輸入流超出1M大小限制"); return null; } // 將bcache中讀取的input數據寫入infoStream infoStream.write(bCache, 0, readSize); } } catch (IOException e1) { LOGGER.error("輸入流讀取異常"); return null; } finally { try { is.close(); } catch (IOException e) { LOGGER.error("輸入流關閉異常"); } } BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(infoStream.toByteArray()); } }
需要說明的是:
1.在eclipse中無法直接使用Base64Encoder
原來Base64Encoder並不屬於JDK標准庫范疇,但是又包含在了JDK中,如http://moses3017.iteye.com/blog/968854所言。
解決方法:按照如下方法設置 Eclipse導入%JAVA_HOME%\jre\lib目錄下的rt.jar包即可。
Project->Properties,選擇Java Build Path設置項,再選擇Libraries標簽,Add External Jars添加%JAVA_HOME%\jre\lib\rt.jar就可以使用啦!
2.我本地的環境是內網,需要設置代理訪問外網
public static void setProxy(String host, String port) { System.setProperty("proxySet", "true"); System.setProperty("proxyHost", host); System.setProperty("proxyPort", port); }
3.網上看到不少地方有這樣的代碼:
/** * 圖片轉化成base64字符串 * @param inputFile 源圖片文件路徑 * @return */ public static String getImageStr(File inputFile) throws Exception{// 將圖片文件轉化為字節數組字符串,並對其進行Base64編碼處理 InputStream in = null; byte[] data = null; // 讀取圖片字節數組 in = new FileInputStream(inputFile); data = new byte[in.available()]; in.read(data); in.close(); // 對字節數組Base64編碼 BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data);// 返回Base64編碼過的字節數組字符串 }
我剛開始也是這樣寫的,后面下載的圖片一直下載不完全。就是上半部分。
可能跟用URL下載圖片和從本地讀取圖片有關,最后是這樣實現的
public static String readInfoStreamToBytes(InputStream is) { if (is == null) { LOGGER.error("輸入流為null"); return null; } // 字節數組 byte[] bCache = new byte[2048]; int readSize = 0;// 每次讀取的字節長度 int totalSize = 0;// 總字節長度 ByteArrayOutputStream infoStream = new ByteArrayOutputStream(); try { // 一次性讀取2048字節 while ((readSize = is.read(bCache)) > 0) { totalSize += readSize; if (totalSize > PROTECTED_LENGTH) { LOGGER.error("輸入流超出1M大小限制"); return null; } // 將bcache中讀取的input數據寫入infoStream infoStream.write(bCache, 0, readSize); } } catch (IOException e1) { LOGGER.error("輸入流讀取異常"); return null; } finally { try { is.close(); } catch (IOException e) { LOGGER.error("輸入流關閉異常"); } } BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(infoStream.toByteArray()); }