zoukankan      html  css  js  c++  java
  • SpringMVC【八】文件上传和下载

    12、文件上传和下载

    12.1 准备工作

    文件上传是项目开发中最常见的功能之一,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 的组件。

    12.2 文件上传

    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="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
       	<input type="file" name="file"/>
       	<input type="submit" value="upload">
      </form>
      
    4. Controller

      @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. 测试,上传文件成功

    采用 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!

    12.3 文件下载

    文件下载步骤:

    1. 设置 response 响应头
    2. 读取文件 -- InputStream
    3. 写出文件 -- OutputStream
    4. 执行操作
    5. 关闭流 (先开后关)

    代码实现:

    1. Controller

      @RequestMapping(value="/download")
      public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
          //要下载的图片地址
          String  path = request.getServletContext().getRealPath("/statics");
          String  fileName = "1.png";
      
          //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;
      }
      
    2. 前端

      --<a href="${pageContext.request.contextPath}/download">点击下载</a>
      
    3. 测试,文件下载成功

  • 相关阅读:
    Codeforces Round #251 (Div. 2) A
    topcoder SRM 623 DIV2 CatAndRat
    topcoder SRM 623 DIV2 CatchTheBeatEasy
    topcoder SRM 622 DIV2 FibonacciDiv2
    topcoder SRM 622 DIV2 BoxesDiv2
    Leetcode Linked List Cycle II
    leetcode Linked List Cycle
    Leetcode Search Insert Position
    关于vim插件
    Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
  • 原文地址:https://www.cnblogs.com/Songzw/p/13215925.html
Copyright © 2011-2022 走看看