SpringBoot 实现文件上传与下载(完整源码 + 详细教程)

一、前言

在日常开发中,文件上传和下载是非常常见的功能场景,比如用户头像上传、文档下载、附件管理等。本文将基于 SpringBoot 框架,实现一套简洁、通用、可直接上线使用的文件上传与下载接口,包含空文件校验、目录自动创建、文件名防重复、文件不存在处理等核心逻辑。

二、环境准备

SpringBoot 版本:2.x/3.x 通用(本文使用 3.x,jakarta 包)

核心依赖:spring-web(Web 开发必备)

配置文件:application.yml/application.properties

三、核心代码实现

  1. pom.xml 依赖(无需额外依赖,基础 Web 依赖即可)
    xml
bash 复制代码
<dependencies>
    <!-- SpringBoot Web 核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 工具类(可选,简化开发) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
  1. 配置文件(application.yml)
    配置文件上传的存储目录,灵活可配置,无需硬编码:
    yaml
bash 复制代码
server:
  port: 8080


#文件上传配置
file:
上传文件存储路径(Windows:D:/upload  Linux:/home/upload)
  upload-dir: D:/springboot-file-upload
  1. 文件上传下载控制器(FileController)
    完整整合版代码,包含上传 + 下载接口,直接复制使用:
    java
    运行
bash 复制代码
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
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.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.UUID;

/**
 * 文件上传下载控制器
 * @author 你的昵称
 */
@RestController
@RequestMapping("/file")
public class FileController {

    // 从配置文件读取上传目录
    @Value("${file.upload-dir}")
    private String uploadDir;

    /**
     * 文件上传接口
     * @param file 前端传递的文件(form-data 格式)
     * @return 上传结果+唯一文件名
     * @throws IOException IO异常
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws IOException {
        // 1. 空文件校验
        if (file.isEmpty()) {
            return "上传失败:文件不能为空";
        }

        // 2. 自动创建上传目录(不存在则创建)
        File directory = new File(uploadDir);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        // 3. 生成唯一文件名(防止文件名重复覆盖)
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = UUID.randomUUID() + suffix;

        // 4. 构建文件最终存储路径
        File destFile = new File(uploadDir + File.separator + fileName);

        // 5. 写入文件到本地
        file.transferTo(destFile);

        // 返回唯一文件名(前端下载时需要传递此文件名)
        return "上传成功!唯一文件名:" + fileName;
    }

    /**
     * 文件下载接口
     * @param fileName 上传时返回的唯一文件名
     * @param response 响应对象
     * @throws IOException IO异常
     */
    @GetMapping("/download")
    public void download(@RequestParam("fileName") String fileName,
                         HttpServletResponse response) throws IOException {

        // 1. 构建文件完整路径
        String filePath = uploadDir + File.separator + fileName;
        File file = new File(filePath);

        // 2. 文件不存在校验
        if (!file.exists()) {
            response.getWriter().write("下载失败:文件不存在");
            return;
        }

        // 3. 设置下载响应头(告诉浏览器这是下载文件)
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" +
                URLEncoder.encode(fileName, "UTF-8"));

        // 4. 读取文件流,输出到前端
        try (FileInputStream fis = new FileInputStream(file);
             OutputStream os = response.getOutputStream()) {

            byte[] buffer = new byte[1024];
            int len;
            // 循环读取文件,写入响应流
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            os.flush();
        }
    }
}

四、接口说明

  1. 文件上传接口
    请求地址:http://localhost:8080/file/upload
    请求方式:POST
    请求参数:file(文件流,前端使用 form-data 格式传递)
    返回结果:上传成功 / 失败提示 + 唯一文件名
    核心特性:
    自动校验空文件,避免无效上传
    自动创建存储目录,无需手动新建文件夹
    UUID 生成唯一文件名,解决同名文件覆盖问题
  2. 文件下载接口
    请求地址:http://localhost:8080/file/download
    请求方式:GET
    请求参数:fileName(上传接口返回的唯一文件名)
    返回结果:浏览器自动下载文件
    核心特性:
    校验文件是否存在,友好提示
    解决中文文件名乱码问题
    流式输出,支持大文件下载
    五、测试接口
  3. 上传测试
    使用 Postman/Apicap 工具:
    请求方式选 POST,地址填 /file/upload
    Body 选择 form-data,key 填 file,类型选择 File
    选择本地文件,点击发送,返回成功提示 + 唯一文件名
  4. 下载测试
    浏览器 / 接口工具直接请求:http://localhost:8080/file/download?fileName=上传返回的唯一文件名
    浏览器会自动触发文件下载
    六、注意事项
    路径适配:Windows 系统路径用 D:/upload,Linux 系统用 /home/upload
    文件大小限制:SpringBoot 默认文件上传大小有限制,可在配置文件添加:
    yaml
bash 复制代码
spring:
  servlet:
    multipart:
      max-file-size: 10MB  # 单个文件最大大小
      max-request-size: 100MB  # 单次请求最大大小
权限问题:Linux 服务器需确保应用对上传目录有读写权限
生产环境:建议搭配 Nginx 做文件访问代理,或使用云存储(OSS/COS)

七、总结

本文实现的 SpringBoot 文件上传下载功能,代码简洁、逻辑完整、无第三方依赖,非常适合新手学习和中小型项目直接使用。核心知识点:

MultipartFile 处理文件上传

UUID 防止文件名重复

响应流实现文件下载

基础校验提升接口健壮性

需要源码的小伙伴可以直接复制本文代码,开箱即用!有问题欢迎评论区交流~

相关推荐
oneouto2 小时前
锁与try catch的位置引发的思考
java
Java技术小馆3 小时前
Claude Code CLI 命令大全:60 个原生命令一次讲清
前端·后端
zzqssliu3 小时前
Spring Boot + XXL-JOB 搭建淘宝代购系统任务调度中心
java·spring boot·后端
一行代码一行诗++3 小时前
goto语句
java·开发语言·算法
m0_639310793 小时前
大数据技术原理-HDFS的安装与应用
java·大数据·jvm·hadoop·spring·hdfs·eclipse
kunge20133 小时前
Claude Code 工作流中的命令实现与自定义指南
人工智能·后端·架构
明月_清风3 小时前
Go 没有 `class`,如何实现面向对象三要素?与传统 OOP 的深度对比
后端·go
Plastic garden3 小时前
Redis(2) redis的高可用
java·数据库·redis
XiYang-DING3 小时前
【Spring】SpringIoC&DI
java·spring·log4j