lilele200706

 

文件的上传和下载

文件下载

public class FileServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      /**
        * 1.获取下载文件的地址
        * 2.文件的名字
        * 3.设置浏览器支持我们下载文件
        * 4.创建读入文件的流
        * 5.获取写出文件的流
        * 6.创建缓冲区
        * 7.将FileInputStream流写入到缓冲区,使用OutputStream将缓冲区中的数据输出到客户端。
        */
      String fileAddress = "C:\\IdeaProjects\\filedown\\target\\classes\\李全政+java开发+13803894486.doc";
      String fileName = fileAddress.substring(fileAddress.lastIndexOf("\\")+1);
      System.out.println(fileName);
      resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
      FileInputStream in = new FileInputStream(fileAddress);
      ServletOutputStream out = resp.getOutputStream();
      int len = 0;
      byte[] buffer = new byte[1024];
      while((len = in.read(buffer))>0){
          out.write(buffer,0,len);
      }
      in.close();
      out.close();
  }
}

文件上传

servlet实现的

  1. 导包

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
   <dependency>
     <groupId>commons-fileupload</groupId>
     <artifactId>commons-fileupload</artifactId>
     <version>1.4</version>
   </dependency>
   <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
   <dependency>
     <groupId>commons-io</groupId>
     <artifactId>commons-io</artifactId>
     <version>2.6</version>
   </dependency>
   <!--Servlet - JSP -->
   <dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>servlet-api</artifactId>
     <version>2.5</version>
   </dependency>
   <dependency>
     <groupId>javax.servlet.jsp</groupId>
     <artifactId>jsp-api</artifactId>
     <version>2.2</version>
   </dependency>
   <dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>jstl</artifactId>
     <version>1.2</version>
   </dependency>
  1. 编写实现方法。

public class UploadServlet extends HttpServlet implements Serializable {
  private static final long serialVersionUID = 1L;
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      /**
        * 1.创建存放上传文件的路径
        * 2.创建存放大型上传文件的临时路径,可以转为永久存放
        * 3.处理上传的文件,使用common-fileupload,创建DiskFileItemFactory对象,处理文件路径或者大小限制
        * 4.获取ServletFileUpload,可以设置监听器,设置编码,文件大小
        * 5.处理上传文件,获取上传文件的名字,设置上传文件的路径,可以使用UUID
        * 6.获取读入上传文件的流
        * 7.创建写出文件的流
        * 8.关闭流
        * 9.设置返回上传成功的信息。
        */
      //判断上传的文件是普通表单还是带文件的表单
      if(!ServletFileUpload.isMultipartContent(req)){
          return;
      }
      //1.创建存放上传文件的路径,不能重复,时间戳,uuid,MD5,位运算
      String uploadPath = this.getServletContext().getRealPath("WEB-INF/upload");
      File uploadFile = new File(uploadPath);
      if(!uploadFile.exists()){
          uploadFile.mkdir();
      }
      //创建存放大型上传文件的临时路径,不能重复,时间戳,uuid,MD5,位运算
      String tmpPath = this.getServletContext().getRealPath("WEB-INF/tmp");
      File tmpFile = new File(tmpPath);
      if(!tmpFile.exists()){
          tmpFile.mkdir();//
      }
      // 处理上传的文件,一般都需要通过流来获取,我们可以使用 request,.getInputstream(),原生态的文件上传流获取,十分麻烦
      // 但是我们都建议使用 Apache的文件上传组件来实现, common-fileupload,它需要旅 commons-io组件;
      // 创建DiskFileItemFactory对象,处理文件路径或者大小限制
      DiskFileItemFactory factory = new DiskFileItemFactory();
      factory.setSizeThreshold(1024*1024);
      factory.setRepository(uploadFile);
      //2.获取ServletFileUpload
      ServletFileUpload upload = new ServletFileUpload(factory);
      upload.setProgressListener(new ProgressListener() {
          @Override
          public void update(long l, long l1, int i) {
              System.out.println("总大小为:"+l1+",已上传"+l);
          }
      });
      upload.setHeaderEncoding("UTF-8");
      upload.setFileSizeMax(1024*1024*10);
      //3.处理上传文件
      // 把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取
      String msg = "";
      try {
          List<FileItem> fileItems = upload.parseRequest(req);
          for (FileItem fileItem : fileItems) {
              if(fileItem.isFormField()){
                  String name = fileItem.getFieldName();
                  String value = fileItem.getString("UTF-8");
                  System.out.println(name+":"+value);
              }else{
                  //获取上传的路径
                  String uploadName = fileItem.getName();
                  System.out.println("上传的文件名:"+uploadName);
                  if(uploadName.trim()==""||uploadName==null){
                      continue;
                  }
                  //获取上传文件的名字
                  String fileName = uploadName.substring(uploadName.lastIndexOf("/")+1);
                  String fileExtName = uploadName.substring(uploadName.lastIndexOf(".")+1);
                  System.out.println("文件信息【文件名:"+fileName+",后缀名:"+fileExtName+"】");
                  // 可以使用UID(唯一识别的通用码),保证文件名唯一
                  // UUID. randomUUID(),随机生一个唯一识别的通用码;
                  String uuidPath = UUID.randomUUID().toString();
                  //设置存放的路径
                  String realPath = uploadPath + "/" + uuidPath;
                  File realPathFile = new File(realPath);
                  if(!realPathFile.exists()){
                      realPathFile.mkdir();
                  }
                  //获取文件上传的流
                  InputStream in = fileItem.getInputStream();
                  //创建文件输出的流
                  FileOutputStream out = new FileOutputStream(realPath+"/"+fileName);
                  int len = 0;
                  byte[] buffer = new byte[1024 * 1024];
                  while ((len = in.read(buffer))!= -1){
                      out.write(buffer,0,len);
                  }
                  in.close();
                  out.close();

                  msg = "文件上传成功";
                  fileItem.delete();
              }
          }
      } catch (FileUploadException e) {
          e.printStackTrace();
      }

      if(msg.equals("文件上传成功")){
          req.setAttribute("msg",msg);
          req.getRequestDispatcher("WEB-INF/upload.jsp").forward(req,resp);
      }else{
          msg = "请上传文件";
          req.setAttribute("msg",msg);
          req.getRequestDispatcher("WEB-INF/upload.jsp").forward(req,resp);

      }


  }
}

和spring整合后

文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。

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

对表单中的 enctype 属性做个详细的说明:

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。

  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。

  • text/plain:除了把空格转换为 "+" 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。

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

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

  • Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。

  • 而Spring MVC则提供了更简单的封装。

  • Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。

  • Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:

  • CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。

 

文件上传

1、导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-io包;

<!--文件上传-->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
</dependency>

2、配置bean:multipartResolver

注意!!!这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!在这里栽过坑,教训!

<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
  <property name="defaultEncoding" value="utf-8"/>
  <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
  <property name="maxUploadSize" value="10485760"/>
  <property name="maxInMemorySize" value="40960"/>
</bean>

CommonsMultipartFile 的 常用方法:

  • String getOriginalFilename():获取上传文件的原名

  • InputStream getInputStream():获取文件流

  • void transferTo(File dest):将上传文件保存到一个目录文件中

我们去实际测试一下

3、编写前端页面

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

4、Controller

package com.kuang.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;

@Controller
public class FileController {
  //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
  //批量上传CommonsMultipartFile则为数组即可
  @RequestMapping("/upload")
  public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {

      //获取文件名 : file.getOriginalFilename();
      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,0,len);
          os.flush();
    }
      os.close();
      is.close();
      return "redirect:/index.jsp";
}
}

5、测试上传文件,OK!

 

采用file.Transto 来保存上传的文件

1、编写Controller

/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@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";
}

2、前端表单提交地址修改

3、访问提交测试,OK!

 

文件下载

文件下载步骤:

1、设置 response 响应头

2、读取文件 -- InputStream

3、写出文件 -- OutputStream

4、执行操作

5、关闭流 (先开后关)

代码实现:

@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
  //要下载的图片地址
  String path = request.getServletContext().getRealPath("/upload");
  String fileName = "1.jpg";

  //1、设置response 响应头
  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 input=new FileInputStream(file);
  //3、 写出文件--输出流
  OutputStream out = response.getOutputStream();

  byte[] buff =new byte[1024];
  int index=0;
  //4、执行 写出操作
  while((index= input.read(buff))!= -1){
      out.write(buff, 0, index);
      out.flush();
}
  out.close();
  input.close();
  return null;
}

前端

<a href="/download">点击下载</a>

测试,文件下载OK,大家可以和我们之前学习的JavaWeb原生的方式对比一下,就可以知道这个便捷多了!

posted on 2022-01-02 22:06  lilele200706  阅读(121)  评论(0编辑  收藏  举报

导航