记录一个小问题:上传到minio,但是根据链接下载的时候图片破损

这几天在做一个视频推拉流的接口,具体就是在新增页面的时候,调用定时任务,拉流抽帧以及相关的表存储。重点是拉流抽帧。

在获取rtsp流地址的时候,调用抽帧接口,然后返回的是图片的base64编码,最后调用minio上传接口。

刚开始我是这样写的

String imgUrl = fileObjectService.uploadPicture(fileName, new ByteArrayInputStream(imgBase64.getBytes()));

在这里,new ByteArrayInputStream(imgBase64.getBytes()) 直接将 Base64 字符串的字节数据作为输入流上传,而没有将 Base64 字符串解码为原始的二进制图片数据,这也导致了我下载到的图片是破损的。

解决方法

在将 Base64 字符串上传之前,需要先将其解码为二进制数据,然后再上传。以下是修改后的代码:

1. Base64 解码
  • 使用 java.util.Base64 将 Base64 字符串解码为字节数组。

2. 上传解码后的二进制数据
  • 将解码后的字节数组包装为 ByteArrayInputStream,然后上传。

import java.util.Base64;
import java.io.ByteArrayInputStream;

// 假设 imgBase64 是 Base64 编码的图片数据
String imgBase64 = "..."; // 你的 Base64 图片数据

// 1. 解码 Base64 字符串为字节数组
byte[] imageBytes = Base64.getDecoder().decode(imgBase64);

// 2. 将字节数组包装为 InputStream
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);

// 3. 上传图片
String imgUrl = fileObjectService.uploadPicture(fileName, inputStream);

// 4. 记录日志
if (imgUrl != null) {
    log.info("图片上传成功,图片地址: {}", imgUrl);
} else {
    log.error("图片上传失败");
}

详细说明

  1. Base64 解码

    • 使用 Base64.getDecoder().decode(imgBase64) 将 Base64 字符串解码为字节数组。

    • 解码后的字节数组是图片的原始二进制数据。

  2. 创建输入流

    • 使用 ByteArrayInputStream 将字节数组包装为 InputStream

  3. 上传图片

    • 将解码后的二进制数据上传到存储服务。

  4. 日志记录

    • 如果上传成功,记录图片地址;如果失败,记录错误信息。

【注】======================================================================

1、Base64编码的不能包括类似data:image/png;base64这种前缀的,要不然会报

java.lang.IllegalArgumentException: Illegal base64 character 3a
	at java.util.Base64$Decoder.decode0(Base64.java:714)
	at java.util.Base64$Decoder.decode(Base64.java:526)
	at java.util.Base64$Decoder.decode(Base64.java:549)
	at 

从错误信息来看,java.lang.IllegalArgumentException: Illegal base64 character 3a 表明 Base64 字符串中包含非法字符(3a 是字符 : 的 ASCII 码)。Base64 字符串只能包含以下字符:

  • 字母:A-Za-z

  • 数字:0-9

  • 特殊字符:+/

  • 填充字符:=

如果 Base64 字符串中包含其他字符(如 :),会导致解码失败。

一般来说,这种Base64编码文件比较大,得有个5~6MB。所以建议测的时候可以自己另外建一个txt文件,然后读取文件内容即可。

// 读取base64.txt文件内容
                File base64File = new File("D:\\xxx\\xxx\\base64.txt");
                BufferedReader reader = new BufferedReader(new FileReader(base64File));
                StringBuilder base64Content = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    base64Content.append(line);
                }
                reader.close();

                // 将文件内容赋值给imgBase64变量
                String imgBase64 = base64Content.toString();
                log.info("设备{}的图片base64编码:{}", deviceId, imgBase64);

完整样例

import java.util.Base64;
import java.io.ByteArrayInputStream;

// 假设 imgBase64 是 Base64 编码的图片数据
// String imgBase64 = "..."; // 你的 Base64 图片数据

try {
    // 1. 去除 Data URL 前缀(如果存在)
    if (imgBase64.startsWith("data:image")) {
        imgBase64 = imgBase64.split(",")[1];
    }

    // 2. 验证 Base64 字符串是否合法
    if (!imgBase64.matches("^[A-Za-z0-9+/]+={0,2}$")) {
        throw new IllegalArgumentException("非法的 Base64 字符串");
    }

    
    // 读取base64.txt文件内容
                File base64File = new File("D:\\xxx\\xxx\\base64.txt");
                BufferedReader reader = new BufferedReader(new FileReader(base64File));
                StringBuilder base64Content = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    base64Content.append(line);
                }
                reader.close();

                // 将文件内容赋值给imgBase64变量
                String imgBase64 = base64Content.toString();
                log.info("设备{}的图片base64编码:{}", deviceId, imgBase64);

    // 3. 解码 Base64 字符串为字节数组
    byte[] imageBytes = Base64.getDecoder().decode(imgBase64);

    // 4. 将字节数组包装为 InputStream
    ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);

    // 5. 上传图片
    String imgUrl = fileObjectService.uploadPicture(fileName, inputStream);

    // 6. 记录日志
    if (imgUrl != null) {
        log.info("图片上传成功,图片地址: {}", imgUrl);
    } else {
        log.error("图片上传失败");
    }
} catch (IllegalArgumentException e) {
    log.error("Base64 字符串非法: {}", imgBase64, e);
    throw new RuntimeException("Base64 字符串非法,请检查数据格式");
} catch (Exception e) {
    log.error("图片上传失败", e);
    throw new RuntimeException("图片上传失败", e);
}

详细说明

  1. 去除 Data URL 前缀

    • 如果 Base64 字符串以 data:image/png;base64, 开头,使用 split(",") 去除前缀,只保留 Base64 编码部分。

  2. 验证 Base64 字符串

    • 使用正则表达式 ^[A-Za-z0-9+/]+={0,2}$ 验证 Base64 字符串是否合法。

    • 如果字符串中包含非法字符(如 :),会抛出 IllegalArgumentException

2、 如果在打日志断点的时候,idea的console控制台看不到整个日志(因为图片的base64很大)。

可以修改这个文件

保存配置,再重启Idea就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值