SpringMVC文件上传功能实例解析

 更新时间:2017年03月09日 10:30:58   作者:MrSaber  
这篇文章主要介绍了SpringMVC文件上传功能实例解析,非常不错,具有参考借鉴价值,需要的朋友可以参考下

说明:

文件上传的途径

  文件上传主要有两种方式:

  1.使用Apache Commons FileUpload元件。

  2.利用Servlet3.0及其更高版本的内置支持。

客户端编程

  1.为了上传文件,必须将HTML表格的enctype属性值设为multipart/form-data,像下面这样:

<form action="action" enctype="multipart/form-data" method="post">
  Select a file<input type="file" name="fieldName"/>
  <input type="submit" value="Upload"/>
</form>

  2.在HTML5之前,如果要想上传多个文件,必须使用多个文件input元素。但是,在HTML5中,通过在input元素中引入多个multiple属性,使得多个文件的上传变得更加简单,下面均可使一个上传框支持多个文件上传。

<input type="file" name="fieldName" multiple/>
<input type="file" name="fieldName" multiple="multiple"/>
<input type="file" name="fieldName" multiple=""/>

MultipartFile接口

  在SpringMVC中处理已经上传的文件十分简单,上传到SpringMVC应用程序中的文件会被包在一个MultipartFile对象中,你唯一要做的事情就是用类型为MultipartFile的属性编写一个Domain类。就像下面这样:

package domain;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
import java.util.List;
public class Product implements Serializable {
  //实现了这个接口,可以安全的将数据保存到HttpSession中
  private long id;
  private String name;
  private String description;
  private String price;
  //在Domain类中加入MultipartFile类型的属性,用来保存上传的文件
  private List<MultipartFile> images;
  public List<MultipartFile> getImages() {
    return images;
  }
  public void setImages(List<MultipartFile> images) {
    this.images = images;
  }
  ......多个get和set方法。

  MultipartFile接口提供了以下方法:

Modifier and Type Method and Description
byte[] getBytes()Return the contents of the file as an array of bytes.
String getContentType()Return the content type of the file.
InputStream getInputStream()Return an InputStream to read the contents of the file from.
String getName()Return the name of the parameter in the multipart form.
String getOriginalFilename()Return the original filename in the client's filesystem.
long getSize()Return the size of the file in bytes.
boolean isEmpty()Return whether the uploaded file is empty, that is, either no file hasbeen chosen in the multipart form or the chosen file has no content.
void transferTo(File dest)Transfer the received file to the given destination file.

实例:用CommonsFileUpLoad上传文件

导入Jar包及配置环境变量

编写视图

代码:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Add Product Form</title>
</head>
<body>
<form:form action="product_save" method="post" commandName="product" enctype="multipart/form-data">
  <fieldset>
    <legend>Add a Product</legend>
    <p>
      <label for="name">ProductName</label>
      <form:input type="text" id="name" name="name" tabindex="1" path="name"/>
    </p>
    <p>
      <label for="description">ProductDescription</label>
      <form:input type="text" id="description" name="description" tabindex="2" path="description"/>
    </p>
    <p>
      <label for="price">ProductPrice</label>
      <form:input type="text" id="price" name="price" tabindex="3" path="price"/>
    </p>
    <p>
      <label for="image">ProductImage</label>
      <input type="file" name="images[0]">
    </p>
    <p>
      <input type="reset">
      <input type="submit">
    </p>
  </fieldset>
</form:form>
</body>
</html>

说明:

  首先为了上传文件,必须将HTML表格的enctype属性值设为multipart/form-data
  其次,在HTML5之前,如果要想上传多个文件,必须要用到多个文件input元素。
  但是在HTML5,通过在Input元素中引入过个multiple属性,使得多个文件上传变得更加简单。

<input type="file" name="fieldName" multiple/>
<input type="file" name="fieldName" multiple="multiple"/>
<input type="file" name="fieldName" multiple=""/>

图示:

 

编写控制器

package controller;
import domain.Product;
import Service.ProductService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
@Controller
public class ProductController {
  private static final Log logger=LogFactory.getLog(ProductController.class);
  @Autowired
  private ProductService productService;
  @RequestMapping(value = "/product_input")
  public String inputProduct(Model model)
  {
    logger.info("inputProduct called");
    model.addAttribute("product",new Product());
    return "ProductForm";
  }
  @RequestMapping(value = "/product_save",method = RequestMethod.POST)
  public String saveProduct(HttpServletRequest servletRequest, @ModelAttribute Product product, 
BindingResult bindingResult,Model model)
  {
    List<MultipartFile> files= product.getImages();
    System.out.println("文件数量是"+files.size());
    if(null!=files&&files.size()>0)
    {
      for (MultipartFile file:files)
      {
        String fileName=file.getOriginalFilename(); //获得文件名称
        File imagFile = new File(servletRequest.getServletContext().getRealPath("/image"),fileName);try {
          file.transferTo(imagFile);//用于将文件写到服务器本地
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    model.addAttribute("product",product);
    return "ProductDetails";
  }
  @RequestMapping(value = "/product_view/{id}")
  public String viewProduct(@PathVariable Long id,Model model)
  {
    Product product =productService.get(id);
    model.addAttribute("product",product);
    return "ProductDetails";
  }
}

配置文件

  你可以看到我们在SpringMVC的配置文件中配置了一个名为multipartResolver的Bean。

  基于servlet的multipartresolver实现Apache Commons FileUpload 1.2或以上。
  提供“maxuploadsize”、“maxinmemorysize”和“defaultencoding”设置bean的属性(继承commonsfileuploadsupport)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
  <context:component-scan base-package="controller"/>
  <context:component-scan base-package="Service"/>
  <!--
   <mvc:annotation-driven>元素注册用于支持基于注解的控制器的请求处理方法的Bean对象。
    详解:https://my.oschina.net/HeliosFly/blog/205343
  -->
  <mvc:annotation-driven></mvc:annotation-driven>
  <bean id="viewResolver"
     class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
  <!--resources 元素指示SpringMVC那些静态资源需要单独处理-->
  <mvc:resources mapping="/image/**" location="/image/"/>
  <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="2000000"/>
  </bean>
</beans>

说明:

  resources 元素指示SpringMVC那些静态资源需要单独处理,此处我们要单独处理的是image,如果不单独处理而是经过dispatcher的话,就会发生404错误.

实例:用Servlet3及其更高版本上传文件

说明:

  有了Servlet3,就不需要Commons FileUpload 和Commons IO元件了.因为在Servlet3中内置了上传文件的特性.
  幸运的是Domain类和Controller类基本不变,我们仅仅需要修改一下配置文件。

配置文件:

修改Web.xml

  我们可以看到实在dispatcher的基础上添加了配置项:multipart-config

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <multipart-config>
      <max-file-size>20848820</max-file-size>
      <!--上传内文件的最大容量-->
      <max-request-size>418018841</max-request-size>
      <!--表示多部分HTTP请求允许的最大容量-->
      <file-size-threshold>1048576</file-size-threshold>
      <!--超过这个容量将会被写到磁盘中-->
      <location>/image/</location>
      <!--要将已上传的文件保存到磁盘中的位置-->
    </multipart-config>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--Spring中文乱码拦截器-->
  <filter>
    <filter-name>setcharacter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>setcharacter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
 </web-app>

SpringMVC配置文件添加多部分解析器

MultipartResolver接口的标准实现,基于Servlet 3.0部分API. To be added as "multipartResolver" bean to a Spring DispatcherServlet context, without any extra configuration at the bean level.
 <bean id="MultipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></bean>

实例:为多文件上传添加一个进度条

说明:

  我们关注的是HTML5 input元素的change事件,当input元素的值发生改变时,他就会被触发。其次,我们还关注XMLHttpRequest对象中添加progress事件。XMLHttpRequest自然是AJAX的骨架。当异步使用XMLHttpRequest对象上传文件的时候就会持续地触发progress事件,直到上传进度完成或者取消。通过轻松监听progress事件,可以轻松地检测文件上传操作的进度。

编写Domain和Controller

1.Domain:UploadFile

package domain;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
public class UploadFile implements Serializable {
  private MultipartFile multipartFile;
  public MultipartFile getMultipartFile() {
    return multipartFile;
  }
  public void setMultipartFile(MultipartFile multipartFile) {
    this.multipartFile = multipartFile;
  }
}

2.Controller:Html5FileUploadController类

package controller;
import domain.UploadFile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
@Controller
public class Html5FileUploadController {
  private static final Log logger = LogFactory.getLog(Html5FileUploadController.class);
  @RequestMapping("/html5")
  public String inputProduct()
  {
    return "html5";
  }
  @RequestMapping("/file_upload")
  public void saveFile(HttpServletRequest servletRequest, @ModelAttribute UploadFile file, BindingResult result)
  {
    MultipartFile multipartFile =file.getMultipartFile();
    String filename =multipartFile.getOriginalFilename();
    try {
      File file1 = new File(servletRequest.getServletContext().getRealPath("/image"),filename);
      multipartFile.transferTo(file1);
      System.out.println("已经写人本地文件:"+file1.getName());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

编写HTML5页面

<%--
 Created by IntelliJ IDEA.
 User: zy
 Date: 17-3-8
 Time: 下午10:01
 To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Title</title>
</head>
<body>
  <script>
    var totalFileLength,totalUploaded,fileCount,filesUploaded;
    function debug(s) { //输出调试信息
      var debug = document.getElementById('debug');
      if(debug)
      {
        debug.innerHTML =debug.innerHTML+'</br>'+s;
      }
    }
    function onUploadComplete(e) { //当一个文件上传完成,紧接着开始调用下次upLoadNext();
      totalUploaded+=document.getElementById('files').files[filesUploaded].size;
      filesUploaded++;
      debug('Complete'+filesUploaded+" of "+fileCount);
      debug('totalUploaded:'+totalUploaded);
      if(filesUploaded<fileCount)
      {
        upLoadNext();
      }
    }
    function onUploadFailed() {
      alert("Error uploading file");
    }
    function onUploadProgress(e) {//当进度发生改变时,改变进度条
      if(e.lengthComputable)
      {
        var percentComplete =parseInt((e.loaded+totalUploaded)*100/totalFileLength);
        var bar = document.getElementById("bar");
        bar.style.width=percentComplete+"%";
        bar.innerHTML =percentComplete+"% complete";
      }
      else
      {
        debug('unable to compute');
      }
    }
    function upLoadNext() { //将XMLHttpRequest对象的progress事件添加到onLoadProgress并将load事件和error事件分别绑定到对应方法。
      var xhr = new XMLHttpRequest();
      var fd =new FormData();
      var file =document.getElementById('files').files[filesUploaded];
      fd.append("multipartFile",file);
      xhr.upload.addEventListener("progress",onUploadProgress,false);
      xhr.addEventListener("load",onUploadComplete,false);
      xhr.addEventListener("error",onUploadFailed,false);
      xhr.open("POST","file_upload");
      debug('uploading'+file.name);
      xhr.send(fd);
    }
    function onFileSelect(e) { //当选择的文件发生改变时,重新获取并打印现在所选的文件信息
      var files =e.target.files;
      var output=[];
      fileCount =files.length;
      totalFileLength =0;
      for(var i=0;i<fileCount;i++)
      {
        var file =files[i];
        output.push(file.name,'(',file.size,'bytes',')',file.lastModifiedDate.toLocaleDateString());
        output.push("<br/>");
        debug('add'+file.size);
        totalFileLength+=file.size;
      }
      document.getElementById('selectedFiles').innerHTML = output.join('');
      debug('totalFileLength:'+totalFileLength);
    }
    function startUpload() { //当用户点击提交以后开始执行
      totalUploaded=filesUploaded=0;
      upLoadNext();
    }
    window.onload=function () {
      document.getElementById('files').addEventListener('change',onFileSelect,false);
      document.getElementById('upLoadButton').addEventListener('click',startUpload,false);
    }
  </script>
</body>
  <h1>Multipart File Uploads with Progress Bar</h1>
  <div id="bar" style="height:100px;background: #33dd33;width: 0%">
  </div>
<form>
  <input type="file" id="files" multiple>
  <br>
  <output id="selectedFiles"></output>
  <input id="upLoadButton" type="button" value="Upload">
</form>
<div id="debug" style="height: 100%;border: 2px solid green;overflow: auto">
</div>
</html>

说明:

  progressBar div用于展示上传进度,debug div用于显示调试信息。

  执行脚本时,第一件事就是为4个变量分配空间:totalFileLength,totalUploaded,fileCount,filesUploaded;

  1. totalFileLength:主要用于保存上传文件的总长度。
  2. totalUploaded:指示目前已经上传的字节数。
  3. fileCount:包含了要上传的文件数量。
  4. fileUploaded:指示了已经上传的文件数量。

以上所述是小编给大家介绍的SpringMVC文件上传功能实例解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • 浅谈Java堆外内存之突破JVM枷锁

    浅谈Java堆外内存之突破JVM枷锁

    这篇文章主要介绍了浅谈Java堆外内存之突破JVM枷锁,涉及jvm内存分配,jvm垃圾回收,堆外内存的垃圾回收等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java中线程的基本方法使用技巧

    Java中线程的基本方法使用技巧

    这篇文章主要介绍了Java中线程的基本方法使用技巧,需要的朋友可以参考下
    2017-09-09
  • Java 数据结构与算法系列精讲之队列

    Java 数据结构与算法系列精讲之队列

    这篇文章主要介绍了Java队列数据结构的实现,队列是一种特殊的线性表,只允许在表的队头进行删除操作,在表的后端进行插入操作,队列是一个有序表先进先出,想了解更多相关资料的小伙伴可以参考下面文章的详细内容
    2022-02-02
  • Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的方法

    Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的方法

    这篇文章主要给大家介绍了关于Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们来一起看看吧
    2018-05-05
  • 阿里SpringBoot应用自动化部署实现IDEA版Jenkins

    阿里SpringBoot应用自动化部署实现IDEA版Jenkins

    这篇文章主要为大家介绍了阿里SpringBoot应用自动化部署实现IDEA版Jenkins过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 浅谈关于spring profile的误解

    浅谈关于spring profile的误解

    这篇文章主要介绍了浅谈关于spring profile的误解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 设计模式之构建(Builder)模式 建造房子实例分析

    设计模式之构建(Builder)模式 建造房子实例分析

    构建模式主要用来针对复杂产品生产,分离部件构建细节,以达到良好的伸缩性,考虑到设计模式来源于建筑学,因此举一个建造房子的例子,需要的朋友可以参考下
    2012-12-12
  • SpringBoot读写xml上传到AWS存储服务S3的示例

    SpringBoot读写xml上传到AWS存储服务S3的示例

    这篇文章主要介绍了SpringBoot读写xml上传到S3的示例,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下
    2020-10-10
  • Maven发布项目到Nexus私有服务器

    Maven发布项目到Nexus私有服务器

    本文主要介绍了Maven发布项目到Nexus私有服务器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Java实现带GUI的气泡诗词效果

    Java实现带GUI的气泡诗词效果

    这篇文章主要为大家介绍了如何利用Java实现带GUI的气泡诗词效果,文中的示例代码讲解详细,对我们学习Java有一定帮助,感兴趣的可以了解一下
    2022-12-12

最新评论