IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringCloud 下 MultipartFile 序列化(JSON)出错的解决方案 -> 正文阅读

[Java知识库]SpringCloud 下 MultipartFile 序列化(JSON)出错的解决方案

1、需求

在SpringCloud架构下,用户向客户端上传文件,客户端调用文件处理微服务去处理文件

2、问题

客户端文件处理服务间传递文件时,想直接把 MultipartFile 转为 json,但出现异常。

在这里插入图片描述

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.io.FileDescriptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])

分析:客户端接收到的是 MultipartFile 文件;要把文件传给文件处理微服务,但直接把 MultipartFile 传给文件服务是不行的。 MultipartFile 不能序列化(或者比较麻烦);

有人说在实体类上加注解,忽略掉MultipartFile属性;@JSONField(serialize = false),但是我的实体类没有 MultipartFile 属性。

经过一番查找,找到了一个合适的解决方案。

3、解决方案

3.1、原理图

在这里插入图片描述

  • 客户端接收到 MultipartFile 文件

  • 通过 MultipartFilegetBytes() 方法转为 byte[] 数组

  • 通过 Base64 工具类把 byte[] 数组转为 Base64字符串,并发送给 文件处理服务

  • 文件处理服务收到 Base64字符串时,再用 Base64 工具类把 字符串转为 byte[] 数组

  • byte[] 作为输入流,从中读取数据,写入输出流,完成文件的存储

3.2、实现步骤

1)MultipartFile 转 byte[]

客户端接收到客户上传的MultipartFile文件

 @PostMapping("/add")
 public String add(
     @RequestParam("file") MultipartFile file
 ) {
     // ...
     byte[] bytes = file.getBytes();
     // 同时获取文件类型;实现步骤省略...
     String fileType = file.getOriginalFilename()...
     // ...
 }

2)byte[] 转 Base64 字符串

工具类 org.apache.tomcat.util.codec.binary.Base64

byte[] 转为字符串后,可以发送给 文件处理服务,同时把文件类型也一起发送;因为从 byte[] 中解析文件类型比较麻烦

String bytesStr = Base64.encodeBase64String(bytes);

3)Base64 字符串 转 byte[]

文件处理服务 收到 字符串后,再转为 byte[]

byte[] bytes = Base64.decodeBase64(bytesStr);

4)从 byte[] 中读取文件并保存

    /**
     * 保存 byte[] 形式的文件
     * @param bytesOfFile 以 byte[] 形式存储的文件
     * @param fileType 文件类型
     * @param saveDir 存储目录
     * @return
     */
    public static String saveFileByBytes(
            byte[] bytesOfFile,
            String fileType,
            String saveDir){

        // 输入流
        BufferedInputStream bis = null;
        // 输出流
        BufferedOutputStream bos = null;

        String fileName = "";
        try {
            // 输入流
            bis = new BufferedInputStream(new ByteArrayInputStream(bytesOfFile));
            // 输出流
            // --- 新文件(名 + 类型);雪花算法省略...
            fileName = SnowflakeUtil.getInstance().nextId() + "." + fileType;
            bos = new BufferedOutputStream(new FileOutputStream(new File(saveDir, fileName)));
            int readLen;
            byte[] buf = new byte[8192];
            while ((readLen = bis.read(buf)) > -1) {
                bos.write(buf, 0, readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.info("文件存储异常!");
            return "_err";
        } finally {
            // 关闭
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 返回保存后的文件名
        return fileName;
    }
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 00:56:31  更:2022-09-04 01:01:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:04:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码