使用IO流实现File和MutipartFile文件类型之间的互转

在Java开发中,处理文件上传和下载是常见的任务。而在Spring框架中,MultipartFile是处理文件上传的常用类,它提供了方便的方法来操作上传的文件。但有时候我们需要在不同的场景中进行文件类型的转换,比如将File类型转换为MultipartFile类型或者将MultipartFile类型转换为File类型。本文将介绍一种使用IO流实现File和MultipartFile文件类型之间的互转的方法,并且解决了一些已知的问题和限制。

前言

在实际开发中,常见的文件类型转换方法有两种:

  1. 使用CommonsMultipartFile(在Spring Web 6中被废弃,同时又与Spring Boot 3冲突)
  2. 使用org.springframework.mock.web.MockMultipartFile转换(一般生产环境不使用这个方法)

然而,在某些情况下,这些方法可能并不适用。因此,本文提供了第三种方法,通过自定义实现来完成File和MultipartFile之间的互转。

方案

我们提供了一个名为MyFileUtil的工具类,其中包含了两个静态方法:

  1. fileToMultipartFile(File file, String fieldName):将File类型转换为MultipartFile类型。
  2. multipartFileToFile(MultipartFile multipartFile):将MultipartFile类型转换为File类型。
实现细节

以下是具体的实现细节:

File转MultipartFile
public static MultipartFile fileToMultipartFile(File file, String fieldName) throws IOException {
    try {
        if (file == null || !file.exists()) {
            throw new FileNotFoundException("文件未找到:" + file);
        }
        byte[] content = Files.readAllBytes(file.toPath());
        return new ByteArrayMultipartFile(content, file.getName(), fieldName, Files.probeContentType(file.toPath()));
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        // 删除临时文件
        file.delete();
    }
}

该方法首先读取文件的内容到一个字节数组中,然后利用自定义的ByteArrayMultipartFile类构造一个MultipartFile对象,并返回。

MultipartFile转File
public static File multipartFileToFile(MultipartFile multipartFile) throws IOException {
    if (multipartFile.isEmpty()) {
        throw new IOException("传入的MultipartFile为空");
    }
    String originalFilename = multipartFile.getOriginalFilename();
    String tempFileSuffix = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf('.')) : ".tmp";
    File tempFile = File.createTempFile("temp", tempFileSuffix);
    try (InputStream ins = multipartFile.getInputStream();
         OutputStream os = new FileOutputStream(tempFile)) {
        byte[] buffer = new byte[8192];
        int bytesRead;
        while ((bytesRead = ins.read(buffer)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
    }
    return tempFile;
}
MyFileUtil完整代码
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.file.Files;


/**
 * @author RainbowCloud
 */
public class MyFileUtil {

    /**
     * 将 File 转换为 MultipartFile。
     *
     * @param file      要转换的文件
     * @param fieldName 字段名,通常用于表单中的文件字段名
     * @return 转换后的 MultipartFile
     * @throws IOException 如果发生I/O错误
     */
    public static MultipartFile fileToMultipartFile(File file, String fieldName) throws IOException {
        try {
            if (file == null || !file.exists()) {
                throw new FileNotFoundException("文件未找到:" + file);
            }
            byte[] content = Files.readAllBytes(file.toPath());
            return new ByteArrayMultipartFile(content, file.getName(), fieldName, Files.probeContentType(file.toPath()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 删除临时文件
            file.delete();
        }
    }

    /**
     * 将 MultipartFile 转换为 File。
     *
     * @param multipartFile 要转换的 MultipartFile
     * @return 转换后的 File
     * @throws IOException 如果发生I/O错误
     */
    public static File multipartFileToFile(MultipartFile multipartFile) throws IOException {
        if (multipartFile.isEmpty()) {
            throw new IOException("传入的MultipartFile为空");
        }
        String originalFilename = multipartFile.getOriginalFilename();
        String tempFileSuffix = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf('.')) : ".tmp";
        File tempFile = File.createTempFile("temp", tempFileSuffix);
        try (InputStream ins = multipartFile.getInputStream();
             OutputStream os = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = ins.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    }

    /**
     * 内置一个简单的 MultipartFile 实现类,用于File转换
     */
    private static class ByteArrayMultipartFile implements MultipartFile {
        private final byte[] content;
        private final String name;
        private final String originalFilename;
        private final String contentType;

        /**
         * 构造函数
         *
         * @param content         文件内容
         * @param originalFilename 文件原始名字
         * @param name            字段名
         * @param contentType     文件类型
         */
        public ByteArrayMultipartFile(byte[] content, String originalFilename, String name, String contentType) {
            this.content = content;
            this.originalFilename = originalFilename;
            this.name = name;
            this.contentType = contentType;
        }

        @Override
        public String getName() {
            return this.name;
        }

        @Override
        public String getOriginalFilename() {
            return this.originalFilename;
        }

        @Override
        public String getContentType() {
            return this.contentType;
        }

        @Override
        public boolean isEmpty() {
            return (this.content == null || this.content.length == 0);
        }

        @Override
        public long getSize() {
            return this.content.length;
        }

        @Override
        public byte[] getBytes() {
            return this.content;
        }

        @Override
        public InputStream getInputStream() {
            return new ByteArrayInputStream(this.content);
        }

        @Override
        public void transferTo(File dest) throws IOException, IllegalStateException {
            try (OutputStream os = new FileOutputStream(dest)) {
                os.write(this.content);
            }
        }
    }

}
结语

通过本文介绍的方法,我们可以方便地在File和MultipartFile之间进行转换,并且避免了一些已知的问题和限制。这种方法在各种场景下都可以适用,并且不依赖于特定的框架版本或者环境。希望这篇文章对你有所帮助!

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将一个`InputStream`对象换成`MultipartFile`对象,可以按照以下步骤进行操作: 1. 创建一个`ByteArrayOutputStream`对象,将`InputStream`中的数据写入到该对象中。 2. 创建一个`CommonsMultipartFile`对象,将`ByteArrayOutputStream`中的数据作为构造函数的参数传入。 3. 设置`CommonsMultipartFile`对象的文件名和文件类型等信息。 下面是一个Java代码示例: ```java import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItem; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartFile; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; public class InputStreamToMultipartFileConverter { public static MultipartFile convert(InputStream inputStream, String fileName, String contentType) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } byte[] bytes = outputStream.toByteArray(); FileItem fileItem = new DiskFileItem("file", contentType, false, fileName, bytes.length , null); fileItem.getOutputStream().write(bytes); return new CommonsMultipartFile(fileItem); } } ``` 使用时,可以调用`convert()`方法将`InputStream`对象换成`MultipartFile`对象,示例如下: ```java InputStream inputStream = new FileInputStream("test.txt"); MultipartFile multipartFile = InputStreamToMultipartFileConverter.convert(inputStream, "test.txt", "text/plain"); ``` 这样就将`InputStream`换成了`MultipartFile`对象。注意,这里使用了`CommonsMultipartFile`,因此需要在Maven中引入`commons-fileupload`和`commons-io`依赖。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值