使用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳功能

使用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳功能?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、虛擬空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、吳忠網(wǎng)站維護(hù)、網(wǎng)站推廣。

說(shuō)明:

文件上傳的途徑

文件上傳主要有兩種方式:

1.使用Apache Commons FileUpload元件。

2.利用Servlet3.0及其更高版本的內(nèi)置支持。

客戶端編程

1.為了上傳文件,必須將HTML表格的enctype屬性值設(shè)為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之前,如果要想上傳多個(gè)文件,必須使用多個(gè)文件input元素。但是,在HTML5中,通過(guò)在input元素中引入多個(gè)multiple屬性,使得多個(gè)文件的上傳變得更加簡(jiǎn)單,下面均可使一個(gè)上傳框支持多個(gè)文件上傳。

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

MultipartFile接口

在SpringMVC中處理已經(jīng)上傳的文件十分簡(jiǎn)單,上傳到SpringMVC應(yīng)用程序中的文件會(huì)被包在一個(gè)MultipartFile對(duì)象中,你唯一要做的事情就是用類型為MultipartFile的屬性編寫一個(gè)Domain類。就像下面這樣:

package domain;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
import java.util.List;
public class Product implements Serializable {
  //實(shí)現(xiàn)了這個(gè)接口,可以安全的將數(shù)據(jù)保存到HttpSession中
  private long id;
  private String name;
  private String description;
  private String price;
  //在Domain類中加入MultipartFile類型的屬性,用來(lái)保存上傳的文件
  private List<MultipartFile> images;
  public List<MultipartFile> getImages() {
    return images;
  }
  public void setImages(List<MultipartFile> images) {
    this.images = images;
  }
  ......多個(gè)get和set方法。

MultipartFile接口提供了以下方法:

Modifier and TypeMethod and Description
byte[]getBytes()Return the contents of the file as an array of bytes.
StringgetContentType()Return the content type of the file.
InputStreamgetInputStream()Return an InputStream to read the contents of the file from.
StringgetName()Return the name of the parameter in the multipart form.
StringgetOriginalFilename()Return the original filename in the client's filesystem.
longgetSize()Return the size of the file in bytes.
booleanisEmpty()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.
voidtransferTo(File dest)Transfer the received file to the given destination file.

實(shí)例:用CommonsFileUpLoad上傳文件

導(dǎo)入Jar包及配置環(huán)境變量

使用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳功能

編寫視圖

代碼:

<%@ 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>

說(shuō)明:

首先為了上傳文件,必須將HTML表格的enctype屬性值設(shè)為multipart/form-data
其次,在HTML5之前,如果要想上傳多個(gè)文件,必須要用到多個(gè)文件input元素。
但是在HTML5,通過(guò)在Input元素中引入過(guò)個(gè)multiple屬性,使得多個(gè)文件上傳變得更加簡(jiǎn)單。

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

圖示:

使用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳功能 

編寫控制器

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("文件數(shù)量是"+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);//用于將文件寫到服務(wù)器本地
        } 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";
  }
}

配置文件

你可以看到我們?cè)赟pringMVC的配置文件中配置了一個(gè)名為multipartResolver的Bean。

基于servlet的multipartresolver實(shí)現(xiàn)Apache Commons FileUpload 1.2或以上。
提供“maxuploadsize”、“maxinmemorysize”和“defaultencoding”設(shè)置bean的屬性(繼承commonsfileuploadsupport)

<&#63;xml version="1.0" encoding="UTF-8"&#63;>
<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>元素注冊(cè)用于支持基于注解的控制器的請(qǐng)求處理方法的Bean對(duì)象。
    詳解: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那些靜態(tài)資源需要單獨(dú)處理-->
  <mvc:resources mapping="/image/**" location="/image/"/>
  <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="2000000"/>
  </bean>
</beans>

說(shuō)明:

resources 元素指示SpringMVC那些靜態(tài)資源需要單獨(dú)處理,此處我們要單獨(dú)處理的是image,如果不單獨(dú)處理而是經(jīng)過(guò)dispatcher的話,就會(huì)發(fā)生404錯(cuò)誤.

實(shí)例:用Servlet3及其更高版本上傳文件

說(shuō)明:

有了Servlet3,就不需要Commons FileUpload 和Commons IO元件了.因?yàn)樵赟ervlet3中內(nèi)置了上傳文件的特性.
幸運(yùn)的是Domain類和Controller類基本不變,我們僅僅需要修改一下配置文件。

配置文件:

修改Web.xml

我們可以看到實(shí)在dispatcher的基礎(chǔ)上添加了配置項(xiàng):multipart-config

<&#63;xml version="1.0" encoding="UTF-8"&#63;>
<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>
      <!--上傳內(nèi)文件的最大容量-->
      <max-request-size>418018841</max-request-size>
      <!--表示多部分HTTP請(qǐng)求允許的最大容量-->
      <file-size-threshold>1048576</file-size-threshold>
      <!--超過(guò)這個(gè)容量將會(huì)被寫到磁盤中-->
      <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接口的標(biāo)準(zhǔn)實(shí)現(xiàn),基于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>

實(shí)例:為多文件上傳添加一個(gè)進(jìn)度條

說(shuō)明:

我們關(guān)注的是HTML5 input元素的change事件,當(dāng)input元素的值發(fā)生改變時(shí),他就會(huì)被觸發(fā)。其次,我們還關(guān)注XMLHttpRequest對(duì)象中添加progress事件。XMLHttpRequest自然是AJAX的骨架。當(dāng)異步使用XMLHttpRequest對(duì)象上傳文件的時(shí)候就會(huì)持續(xù)地觸發(fā)progress事件,直到上傳進(jìn)度完成或者取消。通過(guò)輕松監(jiān)聽progress事件,可以輕松地檢測(cè)文件上傳操作的進(jìn)度。

編寫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("已經(jīng)寫人本地文件:"+file1.getName());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

編寫HTML5頁(yè)面

<%--
 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) { //輸出調(diào)試信息
      var debug = document.getElementById('debug');
      if(debug)
      {
        debug.innerHTML =debug.innerHTML+'</br>'+s;
      }
    }
    function onUploadComplete(e) { //當(dāng)一個(gè)文件上傳完成,緊接著開始調(diào)用下次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) {//當(dāng)進(jìn)度發(fā)生改變時(shí),改變進(jìn)度條
      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對(duì)象的progress事件添加到onLoadProgress并將load事件和error事件分別綁定到對(duì)應(yīng)方法。
      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) { //當(dāng)選擇的文件發(fā)生改變時(shí),重新獲取并打印現(xiàn)在所選的文件信息
      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() { //當(dāng)用戶點(diǎn)擊提交以后開始執(zhí)行
      totalUploaded=filesUploaded=0;
      upLoadNext();
    }
    window.onload=function () {
      document.getElementById('files').addEventListener('change',onFileSelect,false);
      document.getElementById('upLoadButton').addEventListener('click',startUpload,false);
    }
  </script>
</body>
  <h2>Multipart File Uploads with Progress Bar</h2>
  <div id="bar" >
  </div>
<form>
  <input type="file" id="files" multiple>
  <br>
  <output id="selectedFiles"></output>
  <input id="upLoadButton" type="button" value="Upload">
</form>
<div id="debug" >
</div>
</html>

說(shuō)明:

progressBar div用于展示上傳進(jìn)度,debug div用于顯示調(diào)試信息。

執(zhí)行腳本時(shí),第一件事就是為4個(gè)變量分配空間:totalFileLength,totalUploaded,fileCount,filesUploaded;

  1. totalFileLength:主要用于保存上傳文件的總長(zhǎng)度。
  2. totalUploaded:指示目前已經(jīng)上傳的字節(jié)數(shù)。
  3. fileCount:包含了要上傳的文件數(shù)量。
  4. fileUploaded:指示了已經(jīng)上傳的文件數(shù)量。

使用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳功能

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。

網(wǎng)頁(yè)標(biāo)題:使用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳功能
網(wǎng)站URL:http://muchs.cn/article28/pihocp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)小程序開發(fā)、虛擬主機(jī)、網(wǎng)站排名網(wǎng)站策劃、商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化