SpringBoot文件上传下载工具类完整指南

目录

项目准备

1. Maven依赖

2. 目录结构

文件上传工具类

FileUploadUtil.java

文件下载工具类

FileDownloadUtil.java

控制器示例

FileController.java

配置文件

application.yml

FileConfig.java(配置类)

前端调用示例

HTML页面

注意事项

1. 安全考虑

2. 性能优化

3. 存储考虑

4. 监控和日志

常见问题解决

1. 中文文件名乱码

2. 文件上传大小限制

3. 临时文件清理

4. 文件路径安全

5. 并发上传问题


项目准备

1. Maven依赖

pom.xml中添加必要的依赖:


    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
    
    
        commons-io
        commons-io
        2.11.0
    
    
    
    
        commons-fileupload
        commons-fileupload
        1.4
    

2. 目录结构

src/main/java/com/example/
├── config/           # 配置类
├── controller/       # 控制器
├── utils/           # 工具类
│   ├── FileUploadUtil.java    # 文件上传工具类
│   └── FileDownloadUtil.java  # 文件下载工具类
└── Application.java # 启动类

文件上传工具类

FileUploadUtil.java

package com.example.utils;

import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 文件上传工具类
 * 提供文件上传的各种功能,包括文件校验、路径生成、文件保存等
 */
public class FileUploadUtil {
    
    // 默认上传路径
    private static final String DEFAULT_UPLOAD_PATH = "uploads/";
    
    // 允许的文件类型(可根据需要修改)
    private static final Set ALLOWED_EXTENSIONS = new HashSet<>(Arrays.asList(
        "jpg", "jpeg", "png", "gif", "bmp", "webp",  // 图片格式
        "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx",  // 文档格式
        "txt", "md", "xml", "json",  // 文本格式
        "zip", "rar", "7z"  // 压缩格式
    ));
    
    // 文件大小限制(默认10MB)
    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;
    
    /**
     * 上传单个文件(最简单的方式)
     * @param file 上传的文件
     * @return 上传后的文件路径
     * @throws Exception 上传失败时抛出异常
     */
    public static String uploadFile(MultipartFile file) throws Exception {
        return uploadFile(file, DEFAULT_UPLOAD_PATH);
    }
    
    /**
     * 上传单个文件到指定目录
     * @param file 上传的文件
     * @param uploadPath 上传目录
     * @return 上传后的文件路径
     * @throws Exception 上传失败时抛出异常
     */
    public static String uploadFile(MultipartFile file, String uploadPath) throws Exception {
        // 1. 基础校验
        validateFile(file);
        
        // 2. 创建上传目录
        String fullUploadPath = createUploadDirectory(uploadPath);
        
        // 3. 生成新的文件名(防止重名)
        String newFileName = generateFileName(file.getOriginalFilename());
        
        // 4. 保存文件
        String filePath = fullUploadPath + newFileName;
        saveFile(file, filePath);
        
        // 5. 返回相对路径
        return uploadPath + newFileName;
    }
    
    /**
     * 批量上传文件
     * @param files 文件数组
     * @param uploadPath 上传目录
     * @return 上传成功的文件路径列表
     * @throws Exception 上传失败时抛出异常
     */
    public static List uploadFiles(MultipartFile[] files, String uploadPath) throws Exception {
        List filePaths = new ArrayList<>();
        
        if (files == null || files.length == 0) {
            throw new Exception("没有选择文件");
        }
        
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                String filePath = uploadFile(file, uploadPath);
                filePaths.add(filePath);
            }
        }
        
        return filePaths;
    }
    
    /**
     * 文件校验
     * 检查文件是否为空、大小是否超限、格式是否允许
     */
    private static void validateFile(MultipartFile file) throws Exception {
        // 检查文件是否为空
        if (file == null || file.isEmpty()) {
            throw new Exception("文件不能为空");
        }
        
        // 检查文件大小
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new Exception("文件大小不能超过 " + (MAX_FILE_SIZE / 1024 / 1024) + "MB");
        }
        
        // 检查文件扩展名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw new Exception("文件名不能为空");
        }
        
        String extension = getFileExtension(originalFilename);
        if (!ALLOWED_EXTENSIONS.contains(extension.toLowerCase())) {
            throw new Exception("不支持的文件格式: " + extension);
        }
    }
    
    /**
     * 创建上传目录
     * 如果目录不存在则创建,支持按日期分类
     */
    private static String createUploadDirectory(String uploadPath) throws Exception {
        // 按日期创建子目录
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String dateStr = sdf.format(new Date());
        String fullPath = uploadPath + dateStr + "/";
        
        try {
            Path path = Paths.get(fullPath);
            if (!Files.exists(path)) {
                Files.createDirectories(path);
            }
            return fullPath;
        } catch (IOException e) {
            throw new Exception("创建上传目录失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成新的文件名
     * 使用UUID + 时间戳确保文件名唯一
     */
    private static String generateFileName(String originalFilename) {
        String extension = getFileExtension(originalFilename);
        String timestamp = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid + "_" + timestamp + "." + extension;
    }
    
    /**
     * 获取文件扩展名
     */
    private static String getFileExtension(String filename) {
        if (filename == null || filename.isEmpty()) {
            return "";
        }
        int lastDotIndex = filename.lastIndexOf(".");
        if (lastDotIndex == -1) {
            return "";
        }
        return filename.substring(lastDotIndex + 1);
    }
    
    /**
     * 保存文件到磁盘
     */
    private static void saveFile(MultipartFile file, String filePath) throws Exception {
        try {
            // 方式1:使用transferTo方法(推荐)
            File dest = new File(filePath);
            file.transferTo(dest);
            
            // 方式2:使用流的方式(备选)
            // try (InputStream inputStream = file.getInputStream();
            //      FileOutputStream outputStream = new File

你可能感兴趣的:(Java,spring,boot,后端,java)