文件的上传下载—spring boot

Java中的流

输入输出设备的一种抽象理解,在java中,对数据的输入输出操作都是以“流”的方式进行的。

“流”具有方向性,输入流、输出流是相对的。

当程序需要从数据源读入数据的时候就会开启一个输入流,

相反,写出数据到某个数据源目的地的时候也会开启一个输出流。

数据源可以是文件、内存或者网络等。

MultipartFile类—处理文件上传的文件

是SpringMVC提供简化上传操作的工具类。

在不使用框架之前,都是使用原生的HttpServletRequest来接收上传的数据,文件是以二进制流传递到后端的,然后需要我们自己转换为File类。

MultipartFile主要是用表单的形式进行文件上传,

MultipartFile 的作用

MultipartFile 是 Spring对客户端通过对 HTTPmultipart/form-data 请求中文件数据的封装。它提供了以下功能:

  • 在接收到文件时,可以获取文件的相关属性,比如文件名、文件大小、文件类型等等。

  • 读取文件内容为字节数组或输入流。

  • 将文件保存到磁盘。

MultipartFile 是 Spring 框架中用于处理文件上传的核心接口,并提供了一系列方法用于操作这些文件数据(如获取文件名、文件内容、保存文件等)

//基本信息方法
//返回参数的名称 
//获取表单字段的名称(即 <input type="file" name="file"> 中的 name)
    String getName();
//获取源文件的昵称  获取客户端上传的文件名(如 example.txt)
    String getOriginalFilename();
//返回文件的内容类型  获取文件的 MIME 类型(如 text/plain)
    String getContentType();
//文件内容访问方法
//判断是否为空,或者上传的文件是否有内容
    boolean isEmpty();
//获取文件大小(以字节为单位)
    long getSize();
//将文件内容读取为字节数组。 将文件内容转化成一个byte[] 返回
    byte[] getBytes() throws IOException;
//获取文件的输入流,用于读取文件内容 返回InputStream读取文件的内容
    InputStream getInputStream() throws IOException;

​//文件存储方法
//将上传的文件保存到指定文件系统中
    void transferTo(File dest)
//例如
    File dest = new File("/path/to/save/" + file.getOriginalFilename());
    file.transferTo(dest);
//用于将文件内容传输到指定的 Path 对象中,将上传的文件保存到指定Path路径。    
    transferTo(Path dest)
//例如
    Path path = Paths.get("/path/to/save", file.getOriginalFilename());
    file.transferTo(path);

//资源转换方法
// 将MultipartFile转换为Resource对象
    getResource()
//例如
    Resource resource = file.getResource()

核心组件

  • @RequestParam("file") MultipartFile file: 从请求中提取名为 file 的文件参数。MultipartFile 是 Spring 提供的用于处理文件上传的接口。

  • ResponseEntity<String>: 用于封装 HTTP 响应,包括状态码和响应体(这里是字符串)。

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;
​
@RestController
public class FileUploadController {
​
    private static final String UPLOAD_DIR = "uploads";
​
    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
        //检查文件是否为空 如果客户端上传的文件为空,返回 400 Bad Request 状态码,并提示文件为空
        if (file.isEmpty()) {
            return ResponseEntity.badRequest().body("File is empty.");
        }
​
        try {
            //设置上传目录
            //获取当前工作目录(System.getProperty("user.dir")),并拼接上传目录 uploads。
            //如果上传目录不存在,则创建该目录
            String uploadPath = System.getProperty("user.dir") + File.separator + UPLOAD_DIR;
            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdir();
            }
            //保存文件到服务器
            //构建文件的完整路径(uploadPath + 文件名)。
            //使用 MultipartFile.transferTo() 方法将文件保存到指定路径
            String filePath = uploadPath + File.separator + file.getOriginalFilename();
            file.transferTo(new File(filePath));
            //如果文件保存成功,返回 200 OK 状态码,并提示文件上传成功
            return ResponseEntity.ok("File uploaded successfully: " + file.getOriginalFilename());
        } catch (IOException e) {
            return ResponseEntity.internalServerError().body("Failed to upload file: " + e.getMessage());
        }
    }
}

MultipartFile 是 Spring 对 HTTP 文件上传的封装,提供了简单易用的 API 用于操作文件数据。它的底层实现依赖于 MultipartResolver,支持内存存储和临时文件存储两种方式。通过合理配置和使用,可以高效、安全地处理文件上传功能。

示例代码

private static final String fileDirectory = "D:\\文件\\scriptFiles";

    @Override
    public R<?> addScriptFile(MultipartFile file) {
        try {
            // 校验文件类型
            if (!file.getOriginalFilename().endsWith(".py")) {
                return R.Failed("只支持 .py 文件上传");
            }
            // 生成唯一文件名
            String fileName = UUID.randomUUID().toString() + "-" + file.getOriginalFilename();

            // 尝试从本地文件系统加载文件
            Path filePath = Paths.get(fileDirectory).normalize();
            //将文件路径转换为 URI,然后通过 UrlResource 创建文件资源对象
            Resource resource = new UrlResource(filePath.toUri());

            //resource.getFile():转换为 File 对象,表示目标目录的物理文件路径。
            // staticDir 将指向该目录的绝对路径
            File staticDir = resource.getFile();
            //staticDir.getAbsolutePath():获取 staticDir 的 绝对路径字符串。
            String absolutePath = staticDir.getAbsolutePath();
            //使用 Paths.get() 方法将目录路径和文件名拼接成完整的文件路径
            Path path = Paths.get(absolutePath, fileName);
            // Files.copy():将上传文件的输入流复制到目标路径 path 中。如果目标路径不存在,Files.copy() 会自动创建文件
            Files.copy(file.getInputStream(), path);
            // 生成文件访问链接
            String fileUrl = String.valueOf(path);

            Script script = new Script();
            script.setFileUpload(fileUrl);
            // 将文件链接存入数据库
            return R.Success("文件链接",script);
        } catch (IOException e) {
            return R.Failed("文件保存失败: " + e.getMessage());
        }

    }

Spring ResponseEntity 类—文件下载

在 Spring Boot 中,使用 ResourceHttpHeaders 实现文件下载的核心原理是通过 HTTP 响应将文件内容以流的形式返回给客户端并设置相应的 HTTP 头信息,指示浏览器将响应内容作为文件下载

表示整个 HTTP 响应,包括状态码,标头和正文。我们可以使用它来完全配置 HTTP 响应。如果我们想使用它,我们必须从端点返回它;Spring 会处理其余的部分。

ResponseEntity 扩展了 HttpEntity 类,新增了 status 成员变量,这样,一个 ResponseEntity 基本可以代表完整的 HTTP 的请求或响应了。

Spring ResponseEntity 是一个泛型类型。因此,我们可以使用任何类型作为响应正文

核心组件

  • Resource: Spring 提供的 Resource 接口用于表示文件资源。UrlResourceResource 的一个实现类,用于表示通过 URL 访问的资源(如文件系统中的文件)。

  • HttpHeaders: 用于设置 HTTP 响应头信息。在文件下载中,通常需要设置 Content-Disposition 头,指示浏览器将响应内容作为附件下载。

  • ResponseEntity: 用于封装 HTTP 响应的实体,包括状态码、响应头和响应体。

示例代码

private static final String fileDirectory = "D:\\Users\\username\\files";// 本地文件存储目录
    private static final String fixedFileName = "码表模板.xlsx";// 固定文件名

    @GetMapping("/download")
    @ApiOperation(value = "模板下载")
    public ResponseEntity<Resource> download() {
        try {
            // 1. 尝试从本地文件系统加载文件
            Path filePath = Paths.get(fileDirectory).resolve(fixedFileName).normalize();
            //将文件路径转换为 URI,然后通过 UrlResource 创建文件资源对象
            Resource resource = new UrlResource(filePath.toUri());

            //ClassPathResource 是 Spring 框架中的一个类,用于表示类路径(classpath)上的资源。
            // 它实现了 Spring 的 Resource 接口,提供了一种方便的方式来访问类路径中的文件或资源(如配置文件、静态资源等)。
            //类路径资源通常位于 src/main/resources 目录下(在 Maven/Gradle 项目中),或者被打包到 JAR 文件的根目录中。
            // 2. 如果本地文件不存在,尝试从类路径(src/main/resources/static)加载文件
            if (!resource.exists()) {
                resource = new ClassPathResource("static/" + fixedFileName);
            }

            // 3. 检查文件是否存在
            if (resource.exists()) {
                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                        .body(resource);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (MalformedURLException e) {
            //如果文件路径不合法(如格式错误),捕获异常并返回 500 错误
            return ResponseEntity.internalServerError().build();
        }
    }

    @GetMapping("/downloadFileName")
    @ApiOperation(value = "模板下载—名字")
    public ResponseEntity<Resource> downloadFileName(@RequestParam(value = "fileName") String fileName) {

        try {
            // 1. 尝试从本地文件系统加载文件
            //Paths.get(FILE_DIRECTORY):获取文件存储目录的路径。
            //resolve(fileName):将文件名与目录路径拼接,得到文件的完整路径。
            //normalize():规范化路径,处理路径中的 . 和 ..
            Path filePath = Paths.get(fileDirectory).resolve(fileName).normalize();
            //将文件路径转换为 URI,然后通过 UrlResource 创建文件资源对象
            Resource resource = new UrlResource(filePath.toUri());
            // 2. 如果本地文件不存在,尝试从类路径(src/main/resources/static)加载文件
            if (!resource.exists()) {
                resource = new ClassPathResource("static/" + fileName);
            }

            if (resource.exists()) {
            //HttpHeaders.CONTENT_DISPOSITION:设置响应头 Content-Disposition,指示浏览器将响应内容作为附件下载。
            //attachment:表示文件应作为附件下载。
            //filename:指定下载文件的默认名称。
            //body(resource):将文件资源作为响应体返回。    
                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                        .body(resource);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (MalformedURLException e) {
            //如果文件路径不合法(如格式错误),捕获异常并返回 500 错误
            return ResponseEntity.internalServerError().build();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值