Skip to content

Latest commit

 

History

History
executable file
·
197 lines (147 loc) · 6.77 KB

文件上传和下载.mdx

File metadata and controls

executable file
·
197 lines (147 loc) · 6.77 KB
id title
文件上传和下载
12. 文件上传和下载

文件上传:

文件上传是项目开发中比较常用的功能之一,SpringMVC可以很好的支持文件上传,但是,SpringMVC上下文中默认是没有装配MultipartResolve,因此默认情况下其不能处理文件上传工作。

如果要使用文件上传功能,则需要在上下文中配置MultipartResolve。

前端表单要求:为了能上传文件,必须将表单的method设置为post,并设置enctype设置为multipart/form-data。只有在这种情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。

enctypre属性:

描述
application/x-www-form-urlencoded 在发送前编码所有字符(默认)
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain 空格转换为 "+" 加号,但不对特殊字符编码。

表单代码:

<form method="POST" action="" enctype="multipart/form-data">
  <input type="file" name="file"/>
  <input type="submit"/>
</form>

一旦设置了enctype属性为multipart/form-data,浏览器会采用二进制流的方式处理表单的数据,而对于文件上传的处理涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快陈伟Servlet/Jsp程序员上传文件的最佳选择。

Maven依赖:

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>
  • Servlet3.0规范已经提供方法来处理文件上传,但是这种上传功能只能在Servlet中完成
  • SpringMVC提供了更简单的封装
  • SpringMVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolve实现的
  • SpringMVC使用Apache Commons FileUpload技术实现了一个MultipartResolve实现类:
    • CommonsMultipartResolve类,因此SpringMVC的文件上传功能是需要依赖Apache的该组件的。

注册Bean:

CommonsMultipartResolve注册到容器中:

<!-- 定义文件上传解析器 -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
  <!-- 设定默认编码 -->
  <property name="defaultEncoding" value="utf-8"/>
  <!-- 设定文件上传的最大值为10MB,1024*1024*10 -->
  <property name="maxUploadSize" value="10485760"/>
  <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
  <property name="maxInMemorySize" value="40960"/>
</bean>

Controller处理:

方式一:

@Controller
public class FileController {
  /**
     * @RequestParam("file")将name=file控件得到的文件封装成CommonsMultipartFile对象
     * 批量上传CommonsMultipartFile为数组即可
     */
  @RequestMapping("/upload")
  public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
    //获取上传文件的文件名
    String uploadFileName = file.getOriginalFilename();
    //如果文件名为空,则跳转到首页
    if("".equals(uploadFileName)){
      return "redirect:/index.jsp";
    }
    System.out.println("上传的文件名:"+uploadFileName);

    //上传路径保存位置
    String path = request.getServletContext().getRealPath("/upload");
    //如果路径不存在,则创建
    File realPath = new File(path);
    if(!realPath.exists()){
      realPath.mkdir();
    }
    System.out.println("上传文件保存位置:"+realPath);

    //输入流
    InputStream is = file.getInputStream();
    //文件输出流
    OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));

    //读进写出(读进内存、数组,再写出到本地磁盘)
    int len = 0;
    byte[] buffer = new byte[1024];
    while ((len=is.read(buffer))!=-1){
      os.write(buffer);
      os.flush();
    }
    os.close();
    is.close();
    return "redirect:/index.jsp";
  }
}

说明:

  • InputStream is = file.getInputStream();,获取上传文件输入流
  • OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));
    • 定义一个输出流对象,用于将上传的文件输入流写出到本地
    • new File(realPath,uploadFileName),定义一个File实例,指定文件保存的路径和文件名
  • is.read(buffer),将字节输入流读进字节数组(缓冲区),返回一个整型,如果返回-1,说明读取到字节流末尾,无字节可读。
  • os.write(buffer);os.flush();,从字节数组中将数据写出到本地磁盘

方式二:

@RequestMapping("/upload")
public String upload1(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
  //上传路径保存设置
  String path = request.getServletContext().getRealPath("/upload");
  File realPath = new File(path);
  if (!realPath.exists()) {
    realPath.mkdir();
  }
  System.out.println("上传文件保存位置:" + realPath);
  //通过CommonsMultipartFile的方法直接把上传的文件保存到本地
  file.transferTo(new File(realPath + "/" + file.getOriginalFilename()));
  return "redirect:/index.jsp";
}

使用transferTo()方法将上传的文件保存到本地磁盘

文件下载:

@RequestMapping("/download")
public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {
  //获取文件的路径
  String path = request.getServletContext().getRealPath("/upload");
  //文件名称
  String fileName = "2020-04-12_大洼东湖向海大道_IMG_0471.jpeg";

  //1. 设置响应头
  response.reset();//设置页面不缓存,清空buffer
  response.setCharacterEncoding("UTF-8");
  response.setContentType("multipart/form-data");//以二进制传输
  //设置响应头
  response.setHeader("Content-Disposition",
                     "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));

  File file = new File(path, fileName);
  //2. 读取文件--输入流
  InputStream is = new FileInputStream(file);
  //3. 写出文件--输出流
  ServletOutputStream os = response.getOutputStream();

  int len = 0;
  byte[] buffer = new byte[1024];
  while ((len = is.read(buffer)) != -1) {
    os.write(buffer);
    os.flush();
  }
  os.close();
  is.close();
  return "redirect:index.jsp";
}