javascript
Spring MVC-09循序渐进之文件上传(基于Servlet3.0+Html5客户端上传文件)
- 示例
- 測試
- 源碼
雖然Servlet3.0+中上傳文件,我們在服務端編程即可非常容易,但是用戶體驗卻不是非常友好。單獨的一個HTML表單并不能顯示進度條,或者顯示已經成功上傳的文件數量。
不管是Java小程序,Flash 或者Silverlight都有其局限性,好在html5可以很方便的解決這些問題。
首先HTML5在其DOM中添加了一個File API,它允許訪問本地文件。
示例
工程結構:
UploadedFile.java
package com.artisan.domain;import java.io.Serializable;import org.springframework.web.multipart.MultipartFile;public class UploadedFile implements Serializable {private static final long serialVersionUID = 72348L;private MultipartFile multipartFile;public MultipartFile getMultipartFile() {return multipartFile;}public void setMultipartFile(MultipartFile multipartFile) {this.multipartFile = multipartFile;} }Html5FileUploadController.java
package com.artisan.controller;import java.io.File; import java.io.IOException;import javax.servlet.http.HttpServletRequest;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.RequestMapping; import org.springframework.web.multipart.MultipartFile;import com.artisan.domain.UploadedFile;@Controller public class Html5FileUploadController {private static final Log logger = LogFactory.getLog(Html5FileUploadController.class);@RequestMapping(value = "/html5")public String inputProduct() {return "Html5";}@RequestMapping(value = "/file_upload")public void saveFile(@ModelAttribute UploadedFile uploadedFile,BindingResult bindingResult, Model model) {MultipartFile multipartFile = uploadedFile.getMultipartFile();logger.info("fileName:" + multipartFile.getOriginalFilename());String fileName = multipartFile.getOriginalFilename();try {File file = new File("D:/", fileName);multipartFile.transferTo(file);logger.info("save files successfully");} catch (IOException e) {e.printStackTrace();}} }Spring MVC配置文件
<?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:p="http://www.springframework.org/schema/p"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 掃描控制層的注解,使其成為Spring管理的Bean --><context:component-scan base-package="com.artisan.controller" /><!-- 靜態資源文件 --><mvc:annotation-driven /><mvc:resources mapping="/css/**" location="/css/" /><mvc:resources mapping="/*.jsp" location="/" /><!-- 視圖解析器 --><bean id="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /></bean><!-- SpringMVC上傳文件時,需要配置MultipartResolver處理器 --><bean id="multipartResolver"class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></bean></beans>web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/config/springmvc-config.xml</param-value></init-param><load-on-startup>1</load-on-startup> <multipart-config><max-file-size>-1</max-file-size><max-request-size>418018841</max-request-size><file-size-threshold>1048576</file-size-threshold></multipart-config> </servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 避免中文亂碼 --><filter> <filter-name>characterEncodingFilter</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>前臺頁面:
我們關注的是HTML5 input元素的change事件,當input元素的值發生改變時,就會被觸發。其次,我們還關注XMLHttpRequest對象中添加progress事件。XMLHttpRequest自然是AJAX的骨架。當異步使用XMLHttpRequest對象上傳文件的時候就會持續地觸發progress事件,直到上傳進度完成或者取消。通過輕松監聽progress事件,可以輕松地檢測文件上傳操作的進度。
<!DOCTYPE HTML> <html> <head> <script>var totalFileLength, totalUploaded, fileCount, filesUploaded;//輸出調試信息function debug(s) { var debug = document.getElementById('debug');if (debug) {debug.innerHTML = debug.innerHTML + '<br/>' + s;}}//當一個文件上傳完成,緊接著開始調用下次upLoadNext();function onUploadComplete(e) {totalUploaded += document.getElementById('files').files[filesUploaded].size;filesUploaded++;debug('complete ' + filesUploaded + " of " + fileCount);debug('totalUploaded: ' + totalUploaded); if (filesUploaded < fileCount) {uploadNext();} else {var bar = document.getElementById('bar');bar.style.width = '100%';bar.innerHTML = '100% complete';alert('Finished uploading file(s)');}}//當選擇的文件發生改變時,重新獲取并打印現在所選的文件信息function onFileSelect(e) {var files = e.target.files; // FileList objectvar 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 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 onUploadFailed(e) {alert("Error uploading file");}//將XMLHttpRequest對象的progress事件添加到onLoadProgress并將load事件和error事件分別綁定到對應方法。function uploadNext() {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 startUpload() {totalUploaded = filesUploaded = 0;uploadNext();}window.onload = function() {document.getElementById('files').addEventListener('change', onFileSelect, false);document.getElementById('uploadButton').addEventListener('click', startUpload, false);} </script> </head> <body> <h1>Multiple file uploads with progress bar</h1> <div id='progressBar' style='height:20px;border:2px solid green'><div id='bar' style='height:100%;background:#33dd33;width:0%'></div> </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:100px;border:2px solid green;overflow:auto'> </div> </body> </html>progressBar div用于展示上傳進度,debug div用于顯示調試信息。
執行腳本時,第一件事就是為4個變量分配空間:totalFileLength,totalUploaded,fileCount,filesUploaded;
- totalFileLength:主要用于保存上傳文件的總長度。
- totalUploaded:指示目前已經上傳的字節數。
- fileCount:包含了要上傳的文件數量。
- fileUploaded:指示了已經上傳的文件數量。
測試
初始頁面:
選擇多個文件:
上傳文件:
查看目標目錄:
源碼
代碼已提交到github
https://github.com/yangshangwei/SpringMvcTutorialArtisan
總結
以上是生活随笔為你收集整理的Spring MVC-09循序渐进之文件上传(基于Servlet3.0+Html5客户端上传文件)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring MVC-09循序渐进之文件
- 下一篇: Spring MVC-10循序渐进之文件