乐趣区

jdk1.8 Base64Util Illegal base64 character

jdk1.8 base64 的编码转码
实用场景
最近工作上有个需求,需要根据图片的 url 下载到本地,并且客户端无法访问到 url 只能接收 base64 图片码。因此决定采用 jdk 自带的 Base64 进行编码转码存储。
小插曲
采用了两个工具类:ImageUtil 和 Base64Util。ImageUtil 用于实际操作。Base64Util 用于统一编码格式。
由于 jdk1.7 和 jdk1.8 内置的 Base64 遵守的 RFC 协议不一致,jdk1.7 按照照 RFC1521 实现的,jdk1.8 是按照 rfc4648 和 rfc2045 两个协议来实现的。具体可以从类注释中查询到。由于协议的不同可能导致 jdk1.8 的解码 jdk1.7 编码的数据时抛出 java.lang.IllegalArgumentException: Illegal base64 character a 异常. 因此需要特别注意保持解码编码的一致性。jdk7 的编码结果包含换行;jdk8 的编码结果不包含换行;jdk8 无法解码包含换行的编码结果;

既然得知上述异常产生的由于, 故找到解决方案也很简单。

使用 apache common 包中的 org.apache.commons.codec.binary.Base64 类进行编码和解码;
编码之后或解码之前去除换行符;
编码和解码使用相同的 jdk 版本;

附上代码
ImageUtils
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class ImageUtils {

/**
* base64 转文件地址
*
* @param filePath
* @param base64
* @param fileName
*/
public static void base64ToImg(String filePath, String base64, String fileName) {
File file = null;
// 创建文件目录
File dir = new File(filePath);
if (!dir.exists() && !dir.isDirectory()) {
dir.mkdirs();
}
BufferedOutputStream bos = null;
java.io.FileOutputStream fos = null;
try {
byte[] bytes = Base64Util.decode(base64);
file = new File(filePath + fileName);
fos = new java.io.FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

/**
* 通过 Toolkit 获取 base64
*
* @param url
* @return
* @author caoting
* @date 2018 年 11 月 21 日
*/
public static String getBase64ByImgUrl(String url) {
String suffix = url.substring(url.lastIndexOf(“.”) + 1);
try {
URL urls = new URL(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Image image = Toolkit.getDefaultToolkit().getImage(urls);
BufferedImage biOut = toBufferedImage(image);
ImageIO.write(biOut, suffix, baos);
String base64Str = Base64Util.encode(baos.toByteArray());
return base64Str;
} catch (Exception e) {
return “”;
}

}

public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
int transparency = Transparency.OPAQUE;
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}

/**
* 通过下载二进制流的方式获取 base64
*
* @param imgUrl 图片 url
* @return 返回图片 base64 的字符串
*/
public static String image2Base64(String imgUrl) {

URL url = null;
InputStream is = null;
ByteArrayOutputStream outStream = null;

HttpURLConnection httpUrl = null;
try {

url = new URL(imgUrl);
httpUrl = (HttpURLConnection) url.openConnection();
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 Base64Util.encode(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 imgUrl;
}
}
Base64Util

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.stream.FileImageInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Base64Util{
/**
* 字符串转图片
* @param base64Str
* @return
*/
public static byte[] decode(String base64Str){
byte[] b = null;
BASE64Decoder decoder = new BASE64Decoder();
try {
b = decoder.decodeBuffer(replaceEnter(base64Str));
} catch (IOException e) {
e.printStackTrace();
}
return b;
}

/**
* 图片转字符串
* @param image
* @return
*/
public static String encode(byte[] image){
BASE64Encoder decoder = new BASE64Encoder();
return replaceEnter(decoder.encode(image));
}

public static String encode(String uri){
BASE64Encoder encoder = new BASE64Encoder();
return replaceEnter(encoder.encode(uri.getBytes()));
}

/**
*
* @path 图片路径
* @return
*/

public static byte[] imageTobyte(String path){
byte[] data = null;
FileImageInputStream input = null;
try {
input = new FileImageInputStream(new File(path));
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int numBytesRead = 0;
while((numBytesRead = input.read(buf)) != -1){
output.write(buf, 0, numBytesRead);
}
data = output.toByteArray();
output.close();
input.close();

} catch (Exception e) {
e.printStackTrace();
}

return data;
}

public static String replaceEnter(String str){
String reg =”[\n-\r]”;
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(str);
return m.replaceAll(“”);
}
}

退出移动版