Spring Boot项目中实现文件的上传、下载和预览功能

在Spring Boot项目中实现文件的上传、下载和预览功能,可以通过使用Spring MVC的MultipartFile接口来处理文件上传,并使用HttpServletResponseResource来实现文件下载和预览。下面是如何实现这些功能的完整示例。

1. 引入依赖

确保在pom.xml中引入了Spring Boot的相关依赖。通常情况下,Spring Boot Starter Web已经包含了必要的依赖。

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

2. 创建文件上传、下载和预览的Controller

你可以创建一个FileController来处理文件的上传、下载和预览。

java 复制代码
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

@Controller
@RequestMapping("/files")
public class FileController {

    // 文件保存路径(可以通过配置文件进行配置)
    @Value("${file.upload-dir}")
    private String fileUploadDir;

    // 文件上传
    @PostMapping("/upload")
    @ResponseBody
    public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        // 获取文件名并且保存文件
        String fileName = file.getOriginalFilename();
        Path targetLocation = Paths.get(fileUploadDir).resolve(fileName);
        Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

        // 返回文件下载的URL
        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/files/download/")
                .path(fileName)
                .toUriString();

        return "File uploaded successfully: " + fileDownloadUri;
    }

    // 文件下载
    @GetMapping("/download/{fileName}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) throws MalformedURLException {
        Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();
        Resource resource = new UrlResource(filePath.toUri());

        if (!resource.exists()) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                .body(resource);
    }

    // 文件预览(主要针对图片、PDF等可以直接在浏览器中显示的文件)
    @GetMapping("/preview/{fileName}")
    public ResponseEntity<Resource> previewFile(@PathVariable String fileName) throws MalformedURLException {
        Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();
        Resource resource = new UrlResource(filePath.toUri());

        if (!resource.exists()) {
            return ResponseEntity.notFound().build();
        }

        String contentType = "application/octet-stream";
        try {
            contentType = Files.probeContentType(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .body(resource);
    }
}

3. 配置文件上传目录

application.propertiesapplication.yml中配置文件的上传路径:

bash 复制代码
file.upload-dir=C:/uploads

或者使用application.yml

bash 复制代码
file:
  upload-dir: C:/uploads

你可以将路径配置为你项目的目录,也可以指定到服务器的某个位置。

4. 创建上传目录

确保在你的系统上已经创建了配置文件中指定的上传目录,比如C:/uploads。如果没有创建,可以通过代码在项目启动时自动创建:

java 复制代码
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Component
public class FileUploadDirectoryInitializer implements CommandLineRunner {

    @Value("${file.upload-dir}")
    private String fileUploadDir;

    @Override
    public void run(String... args) throws Exception {
        Path uploadPath = Paths.get(fileUploadDir);
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath);
        }
    }
}

5. 测试上传、下载和预览

5.1 文件上传

你可以使用Postman、cURL或者前端页面来测试文件上传功能。上传文件的URL为:

bash 复制代码
POST http://localhost:8080/files/upload

参数名称为file

5.2 文件下载

你可以通过以下URL下载文件:

bash 复制代码
GET http://localhost:8080/files/download/{fileName}

其中{fileName}是文件的名称。

5.3 文件预览

你可以通过以下URL预览文件(如图片或PDF):

bash 复制代码
GET http://localhost:8080/files/preview/{fileName}

6. 处理大文件上传

对于大文件上传,Spring Boot默认的最大上传文件大小可能不满足需求,可以通过以下配置进行调整:

bash 复制代码
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB

或者在application.yml中:

Lua 复制代码
spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB

7. 文件预览类型支持

通常情况下,浏览器支持预览的文件类型包括图片(如jpegpng)、PDF、文本文件等。如果文件类型不被浏览器支持,通常可以通过文件下载的方式处理。

8. 文件删除功能(可选)

你也可以添加一个删除文件的接口,来删除已上传的文件:

java 复制代码
// 文件删除
@DeleteMapping("/delete/{fileName}")
@ResponseBody
public String deleteFile(@PathVariable String fileName) throws IOException {
    Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();
    Files.deleteIfExists(filePath);
    return "File deleted successfully";
}
相关推荐
不能放弃治疗2 小时前
单 Agent 实现模式
后端
IT_陈寒4 小时前
Redis内存爆了,原来我漏掉了这个致命配置
前端·人工智能·后端
小bo波4 小时前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
fliter5 小时前
最后一块拼图:用 bitvec 构造 IPv4 包,真正做出自己的 Ping
后端
用户3521802454756 小时前
🎆从 Prompt 到 Skill:让 Spring AI Agent 学会"装新技能"
人工智能·spring boot·ai编程
fliter6 小时前
用 Rust 解析并生成 ICMP 包:checksum、nom 与 cookie-factory
后端
蝎子莱莱爱打怪6 小时前
XZLL-IM干货系列 03|消息 ID 设计:一个 UUID 搞不定的事,我用两个 ID 解决了
后端·面试·开源
fliter6 小时前
从 panic 到 Result:用 Rust 重新整理一个 ping 项目的错误处理
后端
森蓝情丶6 小时前
我给 AI 搭了个法庭:一个前端仔的 LangGraph 实战全记录
前端·后端
JensCS猿7 小时前
从 Spring Boot 回看 SSM 框架:手动挡与自动挡的驾驶哲学
后端