SpringBoot--上传文件(MultipartFile & Base64)

前言:

关于springboot使用阿里云 OSS的上传本文不做过多解释,旨在解释MultipartFile 与 Base64,详细的springboot使用阿里云 OSS可以去看作者了另一篇文章: 云服务器--阿里云OSS(2)【Springboot使用阿里云OSS】_aliyun oss springboot-CSDN博客

一、两种上传方式的区别

  • MultipartFile 上传

    • 前端以 form-data(二进制流) 上传

    • Spring Boot 自动解析成 MultipartFile 对象

    • 适合大文件(图片、Excel、视频)

  • Base64 上传

    • 前端把文件转成 Base64 字符串,通过 JSON 一起传递

    • 后端 Base64.getDecoder().decode() 解码成字节数组

    • 适合小文件(头像、人脸照、签名)

👉 选择建议 :大文件用 MultipartFile,小图片/APP直传用 Base64


二、四个案例


1. MultipartFile 上传到项目运行目录

XML 复制代码
<!-- Spring Web(必须,有 MultipartFile) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

📌 说明

MultipartFile 是 Spring MVC 提供的,内置在 spring-boot-starter-web 里

不需要额外依赖

java 复制代码
@RestController
@RequestMapping("/upload")
public class FileUploadController {

    @PostMapping("/local")
    public String uploadToLocal(@RequestParam("file") MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return "文件为空";
        }

        // 获取原始文件名和后缀
        String originalName = file.getOriginalFilename();
        String extName = originalName.substring(originalName.lastIndexOf("."));

        // 新文件名
        String newFileName = UUID.randomUUID().toString() + extName;

        // 项目运行目录
        String dirPath = System.getProperty("user.dir") + "/uploads/";
        File dir = new File(dirPath);
        if (!dir.exists()) dir.mkdirs();

        // 保存文件
        //这里通过目录对象(dir)和文件名(newFileName)创建了一个新的 File 对象
        //表示文件最终要保存的位置和名称。这时候也还没有实际创建文件。
        File targetFile = new File(dir, newFileName);

        //这是 Java NIO 中的方法(通常file是MultipartFile类型或Path类型),用于将源文件的内容传输到目标文件。
        //这个方法会自动处理文件的读写操作,比传统的流操作更简洁。执行后,磁盘上就会出现目标文件了。
        file.transferTo(targetFile);

        return "文件已保存:" + targetFile.getAbsolutePath();
    }
}

📌 解释

  • MultipartFile 自带 transferTo() 方法,能直接保存文件

  • 存放在 项目根目录/uploads/


2. MultipartFile 上传到阿里云 OSS

java 复制代码
<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 阿里云 OSS SDK -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.17.4</version> <!-- 建议用最新稳定版 -->
</dependency>

📌 说明

  • aliyun-sdk-oss 是 OSS 客户端核心依赖

  • 负责 OSSClientBuilder, putObject 等操作

java 复制代码
@Component
public class OssUtil {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.access-key-id}")
    private String accessKeyId;
    @Value("${aliyun.oss.access-key-secret}")
    private String accessKeySecret;
    @Value("${aliyun.oss.bucket-name}")
    private String bucketName;
    @Value("${aliyun.oss.url-prefix}")
    private String urlPrefix;

    public String uploadFile(MultipartFile file, String folder) {
        try {
            String fileName = folder + "/" + UUID.randomUUID() + 
                              file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));

            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, fileName, file.getInputStream());
            ossClient.shutdown();

            return urlPrefix + "/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException("OSS 上传失败", e);
        }
    }
}

使用:

java 复制代码
@PostMapping("/oss")
public String uploadToOss(@RequestParam("file") MultipartFile file) {
    return ossUtil.uploadFile(file, "images");
}

📌 解释

  • 直接把 MultipartFile.getInputStream() 上传到 OSS

  • 返回一个公网可访问 URL


3. Base64 上传到项目运行目录

XML 复制代码
<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

📌 说明

  • Base64 解码用的是 JDK 自带类 java.util.Base64,不需要额外依赖

  • 文件保存用 java.io.FileOutputStream,JDK 自带

java 复制代码
@RestController
@RequestMapping("/upload")
public class Base64UploadController {

    @PostMapping("/base64Local")
    public String uploadBase64ToLocal(@RequestBody Map<String, String> data) throws IOException {
        String base64 = data.get("fileBase64");
        String extName = data.get("extName"); // 例如 ".png"

        // 去掉前缀 data:image/png;base64,
        if (base64.contains(",")) {
            base64 = base64.substring(base64.indexOf(",") + 1);
        }

        // 解码
        byte[] bytes = Base64.getDecoder().decode(base64);

        // 保存路径
        String dirPath = System.getProperty("user.dir") + "/uploads/";
        File dir = new File(dirPath);
        if (!dir.exists()) dir.mkdirs();

        String fileName = UUID.randomUUID().toString() + extName;
        File targetFile = new File(dir, fileName);

        try (FileOutputStream fos = new FileOutputStream(targetFile)) {
            fos.write(bytes);
        }

        return "文件已保存:" + targetFile.getAbsolutePath();
    }
}

📌 解释

  • Base64 → byte[] → 写入文件

  • 一样存到 项目/uploads/


4. Base64 上传到阿里云 OSS

XML 复制代码
<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 阿里云 OSS SDK -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.17.4</version>
</dependency>

📌 说明

  • 解码 Base64 用 JDK 自带,不需要第三方

  • 上传到 OSS 还是用 aliyun-sdk-oss

java 复制代码
@Component
public class OssBase64Util {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.access-key-id}")
    private String accessKeyId;
    @Value("${aliyun.oss.access-key-secret}")
    private String accessKeySecret;
    @Value("${aliyun.oss.bucket-name}")
    private String bucketName;
    @Value("${aliyun.oss.url-prefix}")
    private String urlPrefix;

    public String uploadBase64(String base64, String extName, String folder) {
        try {
            if (base64.contains(",")) {
                base64 = base64.substring(base64.indexOf(",") + 1);
            }

            byte[] bytes = Base64.getDecoder().decode(base64);
            String fileName = folder + "/" + UUID.randomUUID() + extName;

            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, fileName, new ByteArrayInputStream(bytes));
            ossClient.shutdown();

            return urlPrefix + "/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException("Base64 上传失败", e);
        }
    }
}

使用:

java 复制代码
@PostMapping("/base64Oss")
public String uploadBase64ToOss(@RequestBody Map<String, String> data) {
    return ossBase64Util.uploadBase64(data.get("fileBase64"), data.get("extName"), "faces");
}

📌 解释

  • Base64 字符串解码成字节流

  • ByteArrayInputStream 上传到 OSS


三、总结表格

上传方式 存储位置 优点 缺点 适用场景
MultipartFile → 本地 项目目录 高效、原始大小 本地扩展性差 临时文件、本地调试
MultipartFile → OSS 阿里云 高效、适合大文件 需配置 OSS 图片/视频/Excel 上传
Base64 → 本地 项目目录 JSON 方便 文件体积+33%,效率低 小图片/头像
Base64 → OSS 阿里云 JSON 方便 性能开销大,不适合大文件 人脸照/签名/小图片

✅ 最佳实践:

  • 通用文件(大图/Excel/视频) → MultipartFile + OSS

  • 人脸照/头像/小文件 → Base64 + OSS