1.1、环境
电脑环境:Windows 10;
开发工具:IntelliJ IDEA;
JDK环境: Jdk1.8;
1.2、问题
我们在开发过程中,会进场要将网络上的图片资源,下载下来,经过base64编码之后,再将编码后的资源保存下来,或者存储起来,或者交给下游处理;那么该如何实现呢?
着急的朋友可以直接拿源码,这里我使用了一个base64的编码附录如下:
package com.demo.platform.utils;
import sun.misc.BASE64Encoder;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class ImgUtils {
public static String tranUrlToBase64String(String url){
try {
URL urlImg = new URL(url);
HttpURLConnection httpURLConnection = (HttpURLConnection) urlImg.openConnection();
httpURLConnection.addRequestProperty("User-Agent","Mozilla / 4.76");
InputStream is = httpURLConnection.getInputStream();
//定义字节数组大小;
byte[] buffer = new byte[1024];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int rc =0 ;
while((rc = is.read(buffer,0,100))>0){
byteArrayOutputStream.write(buffer,0,rc);
}
buffer = byteArrayOutputStream.toByteArray();
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(buffer);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
String base64Img = tranUrlToBase64String("http://testvpimg.staplescn.com/cn1100708779EA_1_xnl.jpg\n");
System.out.println(base64Img);
Base64Utils.GenerateImage(base64Img,"C:\\test\\2.jpg");//测试
}
}
第2个类:
package com.demo.platform.utils;
import sun.misc.BASE64Decoder;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Base64Utils {
/**
* base64字符串转化成图片
*
* @param imgData 图片编码
* @param imgFilePath 存放到本地路径
* @return
* @throws IOException
*/
@SuppressWarnings("finally")
public static boolean GenerateImage(String imgData, String imgFilePath) throws IOException { // 对字节数组字符串进行Base64解码并生成图片
if (imgData == null) // 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
OutputStream out = null;
try {
out = new FileOutputStream(imgFilePath);
// Base64解码
byte[] b = decoder.decodeBuffer(imgData.replace("data:image/jpeg;base64,", ""));
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {// 调整异常数据
b[i] += 256;
}
}
out.write(b);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
out.flush();
out.close();
return true;
}
}
}
如果不着急的小伙伴可以看下线面的讲解
1、使用JDK自带的URL连接方式,进行URL连接;入参为url地址;
2、使用HttpURLConnection 实体类进行url连接;这里,使用JDK中URL自带的openConnection方法进行连接操作;
3、连接后,将连接后返回的数据以InputStream输入流的形式写入到电脑内存;就相当于别人告诉你水库的地址,你自己用一个水管将水库里的水,通过这个水管Stream,将水流导入到自己的池塘里;这里我们得注意,跟实际生活经验一个道理,你自己的池塘要能容纳的了这么多容量的水,或者及时引入,及时排除;不然内存就会被占满;
4、现在,图片以数据流的形式存储在我们内存,一旦我们电脑突然断电,我们的数据就会丢失的;所以,我们要以持久化的形式保存下来,所谓持久化,通俗的理解就是以相对稳定的保存方式来保存数据,例如以各种文件的形式保存在硬盘,U盘等;这次电脑关机后,下次我还能访问;
5、我们要将内存中的数据读出来,并且进行base64编码,什么叫base64编码,请看这里【base64编码】
6、关于流的操作:我们这里用【字节数组】容器来读取(类似用桶舀水),每次读取,以【字节】的形式读取【输入流】(类比以ml,克,千克,L等单位分度来舀水,你可以理解为有容量刻度的量筒),每次读取100个字节,然后通过【字节数组输出流】些出到byte数组里(可以理解为一个桶),因为桶的容量是1024,我每次放一部分水流进来(100字节),所以,只要不超过水管的容量,就不会异常;之后,我通过 byteArrayOutputStream 这个管道,将这个桶里的水一桶一桶倒入,水进入这个管道,在输出流管道的尽头要用容器来接水,这里我们还是用之前的byte数组容器来装数据,也可以自己新建一个数组容器来装,但是考虑到容器的复用性,这里直接用原来的桶来装(不要问我为什么上游书库舀水的桶可以在下游的水池里再用,我们这块逻辑跟现实有点不一样,没有物理距离一说,上面只是打个比喻);之后就是用BASE64Encoder将这个桶里的数据进行编码;
7、用一个1024大小的byte数组来装管道里所有的数据,为啥能装得下?因为TCP/IP 协议是以包的形式来传输数据,不是说这个图片有5M,这里一股脑都给你把5M的数据都传输给你,而是以包的形式,将数据分批次给你;这里可以理解为用箱子装货物,然后顺着河流往下漂流;而每个箱子的大小,最1024也够用了;为什么要有箱子呢?你全校师生去旅游,不可能全校的人都瞬移到目的地,而是通过坐车或者其他方式,以一定的单位进行传输和移动的;如果是坐车,这个车就可以理解为包的概念;
8、第2个类中,有这么一行代码:
byte[] b = decoder.decodeBuffer(imgData.replace("data:image/jpeg;base64,", ""));
这里是因为,base64编码的图片文件,会带有base64的图片头代码,解码的时候,要去掉,不然无法显示;
完毕~
欢迎关注我的
CSDN博客: https://blog.csdn.net/River_Continent
微信公众号:幕桥社区
知乎:张牧野, https://www.zhihu.com/people/zhang-mu-ye-37-76/activities
简书: https://www.jianshu.com/u/02c0096cbfd3