使用Base64去处理前后端图片交互
- 一、Base64编码介绍
- 二、java.util.Base64 介绍
- 源码分析
- 编码
- 译码
- 三、使用 Base64 前后端图片交互(实操)
- 四、效果展示
- 五、总结
绪论:在此之前小编发过一次前后端交互处理的方式:前后端图片交互的简易方式,但小编觉得它有如下缺点:
- 图片存储后端项目某目录的路径问题,存放不恰当会出问题,需要配置路径映射。
- 图片与目录依赖性太强,数据库所存放的路径也得依赖于交互的路径。
- 实现过程是使用的 I/O 流操作,耗时较长;
- 打成 jar 包后,部署在服务器上,新建文件,读取文件时可能会因路径问题而出现问题难以察觉。
优点:可以在目录里之间看得到图片🤨。
一、Base64编码介绍
Base64 是MIME(Multipurpose Internet Mail Extensions,通用互联网邮件拓展)协议中的一种内容传送编码方式。MIME
是一种用于在互联网上发送邮件、传输文件等的协议,它可以在邮件信息中添加非ASCII字符和二进制数据。
Base64
是一种将二进制编码转换成 ASCII 字符的编码方式。这种编码方式是先把二进制代码划分为一个个24位(3个字节)长的单元,然后把每个 24 位单元划分为4个6位组。每一个6位组按特定要求转换成对应的 base64 编码(64位二进制代码共有64种不同的值,0到63,26个大小写字母占了0-51,0是A,1是B,再后面52-61是十个数字,最后63是表示‘+’,63表示‘/’),这些所编码出来的字符都只包含 ASCII 字符。不难得出将二进制编码最后通过base64编码后就是一个字符串,当然你也可以当成是ASCII编码串。
二、java.util.Base64 介绍
Base64类是 java.util 下的一个工具类
,它实现了 Base64 的编码方式,同时还具备将编码后的结果译码回二进制代码。
源码分析
Base64 类的构造方法的访问权限是私有的,它主要对外提供了两个静态方法。
public class Base64 {
private Base64() {}
public static Encoder getEncoder() {
return Encoder.RFC4648;
}
public static Decoder getDecoder() {
return Decoder.RFC4648;
}
getEncoder()
方法是去获得Base64内部类Encoder编码器对象。
getDecoder
方法是去获得Base64内部类Decoder译码器对象。
(其他多余的方法不管,小编这只说这前后端图片交互用到的方法)
编码
内部类 Encoder
中的 public String encodeToString(byte[] src)
// 只留了主要的代码
// 这是返回最后编码后字符串的长度
private final int outLength(int srclen) {
// 加2 是为了防止多余的字节没有算进去
// 除以3 乘以4 是因为每三个字节对应4个字符
return 4 * ((srclen + 2) / 3);
}
public byte[] encode(byte[] src) {
int len = outLength(src.length);// 获取编码后ASCII串长度
byte[] dst = new byte[len];
int ret = encode0(src, 0, src.length, dst);// 开始按照编码介绍中的规则进行编码
if (ret != dst.length)
return Arrays.copyOf(dst, ret);
return dst;
}
// 这方法没啥主要的,就是将上面编码好的转成ASCII字符串
public String encodeToString(byte[] src) {
byte[] encoded = encode(src);
return new String(encoded, 0, 0, encoded.length);
}
译码
内部类 Decoder
中的 public byte[] decode(String src)
// 译码的主要方法,将ASCII码转成二进制码
public byte[] decode(byte[] src) {
byte[] dst = new byte[outLength(src, 0, src.length)];
int ret = decode0(src, 0, src.length, dst);
if (ret != dst.length) {
dst = Arrays.copyOf(dst, ret);
}
return dst;
}
// 一般使用这个方法,间接使用上面那个方法.
public byte[] decode(String src) {
return decode(src.getBytes(StandardCharsets.ISO_8859_1));
}
三、使用 Base64 前后端图片交互(实操)
前端代码(以上一篇前后端图片交互的前端代码没区别,只是换了一下路径,这里的前端代码不再需要文件的名称,但由于有的时候前端需要知道文件的名字然后彰显出来,所以还是得知道如何去得到上传文件的名称):
<template>
<el-upload
:action="picAction"
:limit="10"
list-type="picture-card"
accept=".png, .jpg"
:on-success="sucessUpload"
:on-error="errorUpload"
:before-upload="beforeUpload"
>
<el-button size="small" type="primary"> 点击上传 </el-button>
</el-upload>
<el-image :src="imageAction" v-show="flag"/>
</template>
<script setup>
import {ElNotification} from "element-plus"
import {onBeforeUpdate, ref} from 'vue'
import Image from './Image.vue'
const picAction = ref('')// 这个可以说的保存图片发的请求,也可以去当作图片获取的请求
// 也就是说这个可以存到对应的数据库中
const imageAction = ref('')
const flag = ref(false)
function sucessUpload(){
ElNotification({
message: '图片上传成功',
type: 'success',
duration: 1500
})
console.log('success')
flag.value=true
const nowTime = new Date().getTime()
imageAction.value = `http://localhost:8080/images/base64/get?date=${nowTime}`
}
function errorUpload(){
ElNotification({
message: "图片上传失败",
type: 'error',
duration: 1500
})
console.log('error')
}
function beforeUpload(file){
picAction.value = `http://localhost:8080/images/base64/post`
}
</script>
这里有个细节部分,这里测试部分没有像具体项目一样与后端真正有数据交互,就是没有得到图片的Base64编码后的字符串,也就是路径方面会出现恒定的效果,无法发送响应式,这时候小编在后面加个请求参数,使得每次上传完获取图片的请求路径都会发生改变,这样就会有响应式以至于重新渲染。(如下代码特殊点)
const nowTime = new Date().getTime()
imageAction.value = `http://localhost:8080/images/base64/get?date=${nowTime}`
后端代码:
@RestController
@RequestMapping("/images")
@Slf4j
public class ImageController {
private String picBase64Str; // 这个就是可以存到数据库中的字符串,这里因为测试原因,就以成员变量表示出来
@GetMapping("/base64/get")
public void getImageByBase64(HttpServletResponse response) throws IOException {
byte[] imageDecode = Base64.getDecoder().decode(picBase64Str);
response.setContentType("image/jpeg;image/png");
ServletOutputStream out = response.getOutputStream();
out.write(imageDecode);
out.flush();
out.close();
}
@PostMapping("/base64/post")
public void setImageByBase64(@RequestParam("file") MultipartFile file) throws IOException {
byte[] bytes = file.getBytes();
this.picBase64Str = Base64.getEncoder().encodeToString(bytes);
log.info("picBase64Str->{}",picBase64Str);
}
}
知道了 java.util.Base64 工具类的使用,后端代码这部分就很简单了,没什么特殊的地方。唯一需要注意的点,小编可能觉得是使用SpringBoot提供的 MultipartFIle
接口,实现前端传给后端的文件拾取,然后进行操作。
四、效果展示
编码后的字符串
五、总结
- Base64 是 MIME(通用互联网邮件拓展)协议的一种内容传送编码方式,java.util.Base64 工具类实现了它的具体编码和译码操作。
- 使用 Base64 进行前后端图片交互,注意前端部分获取图片的路径问题,需要重新渲染的时候,注意让路径具备响应式。
- MultipartFile 接口在此过程的重要,有它后端处理其文件来方便了太多太多。
- Base64 这种方式处理文件交互也是有缺点的,比如它会增大数据库的压力,在测试阶段也看见了,字符串太长😫。
- 咱就是说还是根据具体情况选具体方式吧。