1、文件下载

使用ResponseEntity实现下载文件的功能

💡 具体实现过程

  1. 引入依赖:首先确保项目中引入了javax.servlet-api的4版本依赖。注意,为了避免潜在的版本冲突和错误,不应该引入其他版本的此依赖。
  2. 使用ResponseEntity:Spring框架提供的ResponseEntity类允许我们定义HTTP响应的各个方面,包括状态码、头部信息和响应体。这使得它特别适合用于实现文件下载功能。
  3. 设置响应头部:为了告诉浏览器响应是一个文件下载,需要设置适当的响应头部,如Content-Disposition
  4. 获取文件:根据需求,从文件系统、数据库或其他地方获取要下载的文件。
  5. 构建响应:使用ResponseEntity构建响应,将文件内容作为响应体,并设置相应的状态码和头部信息。

💡 注意事项

  • 确保已正确配置项目,并且已经引入了javax.servlet-api的4版本依赖。
  • 根据业务需求,调整文件路径和文件名。
  • 对于大文件,考虑使用流式传输,而不是一次性读取整个文件到内存中。
  • 捕获并处理可能出现的异常,例如文件不存在或没有读取权限等。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

@RestController
public class FileController {

	@GetMapping("/download")
	public ResponseEntity download(HttpServletRequest request) throws IOException {
	    ServletContext servletContext = request.getServletContext();
	    String realPath = servletContext.getRealPath("456.jpg");
	    
	    FileInputStream fileInputStream = new FileInputStream(realPath);
	    byte[] bytes = new byte[fileInputStream.available()];
	    
	    fileInputStream.read(bytes);
	    
	    return ResponseEntity
	            .status(HttpStatus.OK)
	            .header("Content-Disposition", "attachment;filename=test.jpg")
	            .body(bytes);
	}
}

这段代码是一个基于Spring框架的简单的文件下载控制器。下面是对每一部分的解释:

  1. @RestController 是一个Spring MVC的注解,用于标注该类为RESTful Web服务的控制器。这意味着返回的数据会自动转换为JSON或其他的HTTP Response Body内容类型。
  2. public class FileController { 定义了一个名为FileController的类。
  3. public ResponseEntity download(HttpServletRequest request) throws IOException { 定义了一个名为download的方法,该方法接收一个HttpServletRequest对象,并抛出一个可能的IOException
  4. ServletContext servletContext = request.getServletContext(); 从HTTP请求中获取ServletContext对象,这个对象提供了有关servlet上下文的信息。
  5. String realPath = servletContext.getRealPath("456.jpg"); 获取在servlet上下文中名为"456.jpg"的文件的真实路径。
  6. FileInputStream fileInputStream = new FileInputStream(realPath); 使用得到的真实路径来创建一个FileInputStream,准备读取文件。
  7. byte[] bytes = new byte[fileInputStream.available()]; 创建一个字节数组,大小是文件可用的字节数。
  8. fileInputStream.read(bytes); 读取文件内容到前面创建的字节数组中。
  9. return ResponseEntity
    返回一个ResponseEntity对象,这是Spring提供的一个类,用于构建HTTP响应。这里设置了HTTP状态为200(OK),并设置了一个名为"Content-Disposition"的HTTP头,其值为"attachment;filename=test.jpg",表示这是一个附件下载,文件名为"test.jpg"。响应体是文件的内容(字节数组)。

总结: 这个方法允许用户下载一个名为"456.jpg"的文件,但当用户下载时,文件名会显示为"test.jpg"。


2、文件上传

在进行文件上传时,务必确保前端form表单的请求方式为post,并添加属性enctype="multipart/form-data"。需要特别注意的是,前端form表单中的button按钮会默认按照get方式提交,这不会受到form上的method属性的影响。因此,为了避免潜在的错误和混淆,建议不要在form表单中使用button按钮进行提交,而是使用input type submit来进行文件的提交操作。

在SpringMVC的框架中,上传的文件会被自动封装到MultipartFile对象中,这个对象提供了获取文件相关信息的便捷方式,如文件名、文件大小等。在处理文件上传的过程中,这个对象扮演着重要的角色。

对于具体的上传步骤,首先需要在前端构建符合要求的form表单,然后在后端通过SpringMVC来处理上传的文件。值得注意的是,在使用SpringMVC 5.3版本进行处理时,可以直接获取到上传文件的后缀名,这为文件处理提供了更多的便利性。

  1. 添加依赖:commons-fileupload commons-fileupload 1.3.1

  2. 在SpringMVC的配置文件中添加配置:
    multipartResolver 这个配置的bean的id必须是这个名字,大小写也要完全一致
    这个bean的id必须叫做multipartResolver , 类的名字是CommonsMultipartResolver
<!--    添加文件上传的bean对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>


3. 控制器方法:

/**
     * 文件上传
     * @return
     */
    @PostMapping("/file")
    public ResponseEntity uploadFile(MultipartFile upFile, HttpServletRequest request) throws IOException {
        String originalFilename = upFile.getOriginalFilename();
        System.out.println("originalFilename = " + originalFilename);
        
        InputStream inputStream = upFile.getInputStream();
        ServletContext servletContext = request.getServletContext();
        
        //必须要关联一个已存在的文件或者文件夹
        String realPath = servletContext.getRealPath("/image");
        realPath += ("/" + originalFilename);
        
        FileOutputStream fileOutputStream = new FileOutputStream(realPath);
        
        IOUtils.copy(inputStream, fileOutputStream);
        
        fileOutputStream.close();
        return ResponseEntity.ok().build();
    }

这段代码是一个基于Java的Spring框架用于上传文件的函数。下面是代码的逐行解释:

  1. public ResponseEntity uploadFile(MultipartFile upFile, HttpServletRequest request) throws IOException { 定义了一个名为uploadFile的公共方法,它接收两个参数:一个是MultipartFile类型的upFile(表示要上传的文件),另一个是HttpServletRequest类型的request(表示HTTP请求)。这个方法声明了抛出IOException
  2. String originalFilename = upFile.getOriginalFilename(); 获取上传文件的原始文件名,并将其存储在originalFilename字符串变量中。
  3. InputStream inputStream = upFile.getInputStream(); 获取上传文件的输入流,并将其存储在inputStream变量中。
  4. ServletContext servletContext = request.getServletContext(); 从HTTP请求中获取ServletContext对象,该对象提供了有关Web应用程序的上下文信息。
  5. String realPath = servletContext.getRealPath("/image"); 获取Web应用程序中/image目录的实际文件系统路径,并将其存储在realPath字符串变量中。
  6. realPath += ("/" + originalFilename); 修改realPath,以包括上传文件的原始文件名,从而指定文件将存储的完整路径。
  7. FileOutputStream fileOutputStream = new FileOutputStream(realPath); 创建一个指向指定路径(realPath)的文件输出流,以便将文件写入该文件系统位置。
  8. IOUtils.copy(inputStream, fileOutputStream); 使用IOUtils.copy方法,将文件从输入流复制到输出流。
  9. fileOutputStream.close(); 关闭文件输出流。这是一个重要的步骤,因为它确保所有缓冲的数据都被写入文件,并释放与流相关联的任何系统资源。
  10. return ResponseEntity.ok().build(); 返回一个HTTP 200(OK)响应,表示文件已成功上传。

通常,在生产环境中,应该包含适当的错误处理(例如,如果上传的文件名已经存在,或者文件未能成功复制)。