java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot MultipartFile转File对象

浅析如何在SpringBoot上传中将MultipartFile转File对象

作者:Micro麦可乐

在我们开发 Spring Boot Web 应用中,文件上传通常通过 MultipartFile 接口接收,但有时我们需要将 MultipartFile 转成标准的 java.io.File 对象,下面我们就来看看具体实现吧

1. 前言

在我们开发 Spring Boot Web 应用中,文件上传通常通过 MultipartFile 接口接收。但有时我们需要将 MultipartFile 转成标准的 java.io.File 对象,便于与依赖本地文件 API 的第三方库(如 Apache POI、Tika、图像处理库等)集成,也便于做临时文件存储与后续处理

你可能会有以下需求:

那么我们就需要将 MultipartFile 转换 java.io.File 对象,本文博主将讲解常见的四种方案,希望小伙伴们阅后能快速掌握。

2. 常见4种转换方案

2.1 使用 transferTo() 方法

transferTo(File) — Spring推荐 最简洁高效

此方式直接调用 MultipartFile.transferTo(dest),将上传内容写入指定文件。

public File convertByTransferTo(MultipartFile multipartFile,String destPath) throws IOException {

    File destFile = new File(destPath);
    // 如果目标目录不存在,则创建
    File parent = destFile.getParentFile();
    if (parent != null && !parent.exists()) {
        parent.mkdirs();
    }
    multipartFile.transferTo(destFile);
    return destFile;
}

优点:代码简洁,直接写入;

缺点:必须确保 MultipartFile 未被多次使用,且目标路径可写

2.2 使用FileUtils.copyInputStreamToFile

需要引入 Apache Commons IO 依赖

<!-- 在 pom.xml 中添加依赖 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

调用 commons-io 中提供的 FileUtils 工具类

public static File convertWithCommonsIO(MultipartFile multipartFile, String destPath) throws IOException {

    File dest = new File(destPath);
    FileUtils.forceMkdirParent(dest);
    FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), dest);
    return dest;
}

优点:极简;FileUtils 自动管理目录创建与流关闭

缺点:需额外 commons-io 依赖

2.3 使用 Java NIO Files.copy

java.nio.file.Files 提供了便捷的方法,将 InputStream 复制到路径(Path)上

public static File convertWithNio(MultipartFile multipartFile, String destPath) throws IOException {

    File destFile = new File(destPath);
    // 如果目标目录不存在,则创建
    File parent = destFile.getParentFile();
    if (parent != null && !parent.exists()) {
        parent.mkdirs();
    }

    try (var in = multipartFile.getInputStream()) {
        return Files.copy(in, destFile, StandardCopyOption.REPLACE_EXISTING);
    }
}

优点:代码简洁;使用现代 NIO API,可选覆盖或保留原有文件

缺点:需管理目录和文件删除

2.4 手动处理输入输出流

手动通过 InputStream/OutputStream 读取 MultipartFile 的内容,并写入 Java File。适用于任何实现

public static File convertWithStream(MultipartFile multipartFile) throws IOException {
    // 创建临时文件,JVM 退出时会尝试删除
    String prefix = "upload_";
    String suffix = "_" + multipartFile.getOriginalFilename();
    File tempFile = File.createTempFile(prefix, suffix);
    try (InputStream in = multipartFile.getInputStream();
         OutputStream out = new FileOutputStream(tempFile)) {
        byte[] buffer = new byte[8192];
        int len;
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
    }
    return tempFile;
}

优点:最通用、可精细控制;无论底层如何实现都可工作

缺点:需要自行管理临时文件删除

3. 全局封装及测试

基于上述的4种方案,我们可以整理成一个工具类,方便后续的使用以及测试

import org.apache.commons.io.FileUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class FileConverter {

    // 方法1: 使用transferTo()方法 (Spring推荐)
    public static File convertUsingTransferTo(MultipartFile file) throws IOException {
        File convertedFile = createTempFile(file);
        file.transferTo(convertedFile);
        return convertedFile;
    }

    // 方法2: 使用Apache Commons IO工具类
    public static File convertUsingCommonsIO(MultipartFile file) throws IOException {
        File convertedFile = createTempFile(file);
        try (InputStream inputStream = file.getInputStream()) {
            FileUtils.copyInputStreamToFile(inputStream, convertedFile);
        }
        return convertedFile;
    }

    // 方法3: 使用Java NIO的Files.copy()
    public static File convertUsingNIO(MultipartFile file) throws IOException {
        File convertedFile = createTempFile(file);
        Path targetPath = convertedFile.toPath();
        Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
        return convertedFile;
    }

    // 方法4: 手动处理输入输出流
    public static File convertManually(MultipartFile file) throws IOException {
        File convertedFile = createTempFile(file);
        try (InputStream inputStream = file.getInputStream()) {
            Files.copy(inputStream, convertedFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }
        return convertedFile;
    }

    // 创建临时文件 小伙伴们可以根据需求改写
    private static File createTempFile(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String prefix = originalFilename != null ? 
                        originalFilename.substring(0, Math.min(originalFilename.length(), 10)) : 
                        "upload_";
        String suffix = originalFilename != null && originalFilename.contains(".") ?
                        originalFilename.substring(originalFilename.lastIndexOf('.')) : 
                        ".tmp";
        
        return File.createTempFile(prefix, suffix);
    }
}

构建测试Controller

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
public class FileUploadController {

    @PostMapping("/upload")
    public ResponseEntity<Map<String, Object>> handleFileUpload(
            @RequestParam("file") MultipartFile file) throws IOException {
        
        Map<String, Object> result = new HashMap<>();
        
        // 使用方法1
        File file1 = FileConverter.convertUsingTransferTo(file);
        result.put("method1", getFileInfo(file1));
        
        // 使用方法2
        File file2 = FileConverter.convertUsingCommonsIO(file);
        result.put("method2", getFileInfo(file2));
        
        // 使用方法3
        File file3 = FileConverter.convertUsingNIO(file);
        result.put("method3", getFileInfo(file3));
        
        // 使用方法4
        File file4 = FileConverter.convertManually(file);
        result.put("method4", getFileInfo(file4));
        
        return ResponseEntity.ok(result);
    }

    private Map<String, Object> getFileInfo(File file) {
        Map<String, Object> info = new HashMap<>();
        info.put("path", file.getAbsolutePath());
        info.put("size", file.length() + " bytes");
        info.put("exists", file.exists());
        return info;
    }
}

4. 方案对比

方法依赖适用场景临时文件控制
transferTo(File)Spring MVC大多数情况首选由 Spring 管理
Apache Commons IOCommons IO已使用Commons IO的项目简便
手动流复制Java标准库需要精细控制流的情况全程可控
Files.copy (NIO)Java标准库高性能需求场景可控

博主推荐:

如果追求最简洁、且 Spring MVC 默认实现足够可靠,推荐 transferTo

如果项目已有 Commons IO,想用最少的代码量,则选择 Apache Commons IO

5. 结语

Spring BootMultipartFileFile 有多种实现方式,各有适用场景。对于大多数应用,推荐使用 Spring 自带的 transferTo() 方法,它在简洁性和性能之间取得了良好平衡。当项目已包含Apache Commons IO时,使用 FileUtils.copyInputStreamToFile 也是不错的选择。

到此这篇关于浅析如何在SpringBoot上传中将MultipartFile转File对象的文章就介绍到这了,更多相关SpringBoot MultipartFile转File对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文