【Base64】前后端图片交互(2)

news2025/1/18 9:10:05

使用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 这种方式处理文件交互也是有缺点的,比如它会增大数据库的压力,在测试阶段也看见了,字符串太长😫。
  • 咱就是说还是根据具体情况选具体方式吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/523762.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习之图像分类(三):VGGNet

系列文章目录 本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;Mobile…

Windows磁盘空间不够,发现DriverStore文件夹特别大

正想安装一个新的VS2022&#xff0c;但是发现C盘的空间已经不足&#xff0c; 显示为红色了&#xff0c;这样不能安装。只好找一下C盘的空间为什么不足了&#xff0c;后来发现有一个目录特别大&#xff0c;这个目录就是DriverStore文件夹。由于电脑已经运行5年了&#xff0c;也…

Java的线程

介绍线程 线程是系统调度的最小单元&#xff0c;一个进程可以包含多个线程&#xff0c;线程是负责执行二进制指令的。 每个线程有自己的程序计数器、栈&#xff08;Stack&#xff09;、寄存器&#xff08;Register&#xff09;、本地存储&#xff08;Thread Local&#xff09…

Linux的基本权限

基本权限 1.权限的概念2.Linux上的用户分类2.1. 如何切换用户&#xff1f; 3.Linux的权限管理3.1. 文件访问者的分类&#xff08;人&#xff09;3.2.文件类型和访问权限&#xff08;文件属性&#xff09;3.2.1. 文件类型3.2.2. 基本权限 3.3. 文件权限值的表示方法3.3.1. 字符表…

Mac中idea快捷键(Keymap->macOS)

背景&#xff1a; mac&#xff1a;MacBook Pro&#xff08;13英寸&#xff0c;M2&#xff0c;2022年&#xff09; 系统版本&#xff1a;12.4 idea快捷键配置&#xff1a;本文快捷键设置基于macOS&#xff08;Keymap->macOS&#xff09; 一、常用快捷键 1.commandF 在当前…

java类和对象2

文章目录 一、Java实例变量和类变量二、Java实例方法和类方法三、Java方法重载四、Java this关键字五、Java包六、Java import语句七、Java访问权限八、Java基本类型的类封装九、Java jar文件总结 一、Java实例变量和类变量 实例变量和类变量的定义 在声明成员变量时&#xf…

微信云开发之云函数小例子

环境 微信开发者工具 Stable 1.06.2303220云开发控制台 v1.5.47 概述 云函数即在云端&#xff08;服务器端&#xff09;运行的函数&#xff0c;代码运行在云端Node.js中。我们可以使用云函数SDK中提供的数据库和存储API进行数据库和存储的操作。 云函数的独特优势在于与微信…

centos,搭建ftp服务;vsftpd

安装vsftpd 使用yum安装vsftpd&#xff1a; yum install -y vsftpd 配置vsftpd 编辑vsftpd配置文件&#xff1a; vim /etc/vsftpd/vsftpd.conf 以下是一些常见的配置项&#xff1a; anonymous_enableNO local_enableYES write_enableYES local_umask022 dirmessage_enableYE…

职场新人必备:10个写进备忘录的职场tips

作为职场新人&#xff0c;如何快速适应、获得成长和提升自己&#xff0c;是每个人都面临的挑战。在这个竞争激烈的职场中&#xff0c;拥有一些实用的职场tips&#xff0c;可以帮助你更好地应对各种挑战&#xff0c;获得成功。在本文中&#xff0c;我们将分享10个写进备忘录的职…

es8388 驱动详解

音频的基本框架 分为三个部分&#xff1a; 1&#xff09; 整体的绿框&#xff0c;为machine&#xff0c;例如你的PC等&#xff0c;负责图中 “线”的部分的关联&#xff0c;及黄色连接器的管理。也就是说不属于 paltform和codec管理的部分&#xff0c;都划归machine管理。 对应…

【Python socket】零基础也能轻松掌握的学习路线与参考资料

Python socket是Python程序语言中与网络编程密切相关的库之一&#xff0c;可以让程序员在网络世界中建立服务和客户端之间的连接。Python socket提供了一系列关键的概念和方法&#xff0c;让用户能够轻松地构建基于网络的程序&#xff0c;如基于TCP和UDP的应用程序。学习Python…

图(Graph)

Graph 图由顶点&#xff08;vertex /ˈvɜːrteks/&#xff09;和边&#xff08;edge /edʒ/&#xff09;组成的一种结构。 顶点的集合V&#xff0c;边的集合是E&#xff0c;所以图记为G &#xff08;V&#xff0c;E&#xff09; 总结: 顶点是一维数组,而边是二维数组; 假如顶点…

Pycharm无法添加Conda新建的虚拟环境

Pycharm无法添加Conda新建的虚拟环境&#xff0c;点击没反应&#xff0c;在idea.log文件中报错&#xff1a;CondaPythonLegacy - Can’t find python path to use, will use conda run instead 1.问题描述&#x1f50d; 在PyCharm中&#xff0c;依次单击File>Settings>P…

Netty核心技术一--Netty介绍和应用场景

1. 学习要求 要求已经掌握了 Java 编程&#xff0c; 主要技术构成&#xff1a; Java OOP 编程、Java 多线程编程、JavaIO 编程 、Java 网络编程、常用的Java 设计模式(比如观察者模式&#xff0c;命令模式&#xff0c;职责链模式 )、常用的数据结构(比如 链表) 2 Netty的介绍…

C++: 计时器类的设计和实现

文章目录 1. 目的2. 功能列表3. 基础功能&#xff1a;获取耗时4. API 设计: Timer 类5. 单元测试6. API 实现 1. 目的 使用 C Class 的形式&#xff0c;封装原本 C语言的获取时间的函数&#xff0c;提供更容易使用的计时器调用。 使用 C03&#xff0c;原因是和先前的线程安全队…

ATT-ACK靶场渗透(一)

开启内网环境 kali攻击机ip为 192.168.88.156 主机发现、端口扫描 进行主机发现 nmap -sS 192.168.88.156/24 -Pn 192.168.88.1和192.168.88.2可能为网关之类的&#xff0c;不管 weblogic漏洞利用 192.168.88.182开放了80端口和7001&#xff08;weblogic&#xff09;端口…

超越预期:ConvNeXt技术催生YOLOv5目标检测巨变 ,实现超准确率

目录 引言一、ConvNeXt的介绍1、目标检测的重要性2、YOLOv5的介绍3、ConvNeXt原理和特点4、ConvNeXt结构 二、相关研究综述1、目标检测的基础原理和流程2、YOLOv5的特点与局限性3、ConvNeXt技术在目标检测中的应用现状 三、ConvNeXt在YOLOv5中的应用与改进1、安装PyTorch和torc…

阿里Java工程规约(来源阿里)

一、应用分层 1.开放接口层&#xff1a; 可直接封装 Service 接口暴露成 RPC 接口&#xff1b;通过 Web 封装成 http 接口&#xff1b;网关控制层等。 2.终端显示层&#xff1a; 各个端的模板渲染并执行显示层。当前主要是 velocity 渲染&#xff0c;JS 渲染&#xff0c;JSP 渲…

[golang gin框架] 33.Gin 商城项目- 微信支付操作相关功能讲解

一.微信支付准备工作 准备工作 申请条件: 个体工商户 、企业、政府及事业单位 PC网站接入支付官网,其他(app,小程序,公众号等)可参考 PC网站接入支付 需要获取内容 appid&#xff1a;应用 APPID&#xff08;必须配置&#xff0c;开户邮件中可查看&#xff09; MCHID&#xff1a…

Java Socket和ServerSocket 使用

在Java中&#xff0c;Socket和ServerSocket是用于创建网络连接的重要类。Socket类用于创建客户端套接字&#xff0c;而ServerSocket类用于创建服务器套接字。在本文中&#xff0c;我们将讨论Socket和ServerSocket的作用、使用方法以及相关代码示例。 Socket的作用 Socket是Jav…