原文: https://howtodoinjava.com/spring-mvc/spring-mvc-multi-file-upload-with-progress-bar/

Spring MVC 示例演示了如何在进度条中使用多文件上传功能,而服务器端代码是用 Spring MVC 编写的。 我已经修改了 spring MVC 多文件上传示例上一篇文章的代码,该示例没有进度栏功能,而是在新的显示页面上显示了上传的图像和数据。

本示例使用纯 JavaScript 代码和 HTML5 控件来构建客户端代码。 如果您想使用任何 JavaScript 库,例如 jQuery 然后请相应地修改代码。

1. 文件上传和进度栏的客户端视图

在下面的productForm.jsp中给出了 spring MVC 项目中的 JSP 文件-但它仅包含 HTML 代码,因此如果您愿意,可以轻松地放置相同的代码。

该文件具有onUploadProgress()函数,该函数显示上传文件的进度。 还有其他功能可以显示上载过程和支持活动的完成情况。

productForm.jsp

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script>
  5. var totalFileLength, totalUploaded, fileCount, filesUploaded;
  6. //To log everything on console
  7. function debug(s) {
  8. var debug = document.getElementById('debug');
  9. if (debug) {
  10. debug.innerHTML = debug.innerHTML + '<br/>' + s;
  11. }
  12. }
  13. //Will be called when upload is completed
  14. function onUploadComplete(e) {
  15. totalUploaded += document.getElementById('files').files[filesUploaded].size;
  16. filesUploaded++;
  17. debug('complete ' + filesUploaded + " of " + fileCount);
  18. debug('totalUploaded: ' + totalUploaded);
  19. if (filesUploaded < fileCount) {
  20. uploadNext();
  21. } else {
  22. var bar = document.getElementById('bar');
  23. bar.style.width = '100%';
  24. bar.innerHTML = '100% complete';
  25. alert('Finished uploading file(s)');
  26. }
  27. }
  28. //Will be called when user select the files in file control
  29. function onFileSelect(e) {
  30. var files = e.target.files; // FileList object
  31. var output = [];
  32. fileCount = files.length;
  33. totalFileLength = 0;
  34. for (var i = 0; i < fileCount; i++) {
  35. var file = files[i];
  36. output.push(file.name, ' (', file.size, ' bytes, ', file.lastModifiedDate.toLocaleDateString(), ')');
  37. output.push('<br/>');
  38. debug('add ' + file.size);
  39. totalFileLength += file.size;
  40. }
  41. document.getElementById('selectedFiles').innerHTML = output.join('');
  42. debug('totalFileLength:' + totalFileLength);
  43. }
  44. //This will continueously update the progress bar
  45. function onUploadProgress(e) {
  46. if (e.lengthComputable) {
  47. var percentComplete = parseInt((e.loaded + totalUploaded) * 100 / totalFileLength);
  48. var bar = document.getElementById('bar');
  49. bar.style.width = percentComplete + '%';
  50. bar.innerHTML = percentComplete + ' % complete';
  51. } else {
  52. debug('unable to compute');
  53. }
  54. }
  55. //the Ouchhh !! moments will be captured here
  56. function onUploadFailed(e) {
  57. alert("Error uploading file");
  58. }
  59. //Pick the next file in queue and upload it to remote server
  60. function uploadNext() {
  61. var xhr = new XMLHttpRequest();
  62. var fd = new FormData();
  63. var file = document.getElementById('files').files[filesUploaded];
  64. fd.append("multipartFile", file);
  65. xhr.upload.addEventListener("progress", onUploadProgress, false);
  66. xhr.addEventListener("load", onUploadComplete, false);
  67. xhr.addEventListener("error", onUploadFailed, false);
  68. xhr.open("POST", "save-product");
  69. debug('uploading ' + file.name);
  70. xhr.send(fd);
  71. }
  72. //Let's begin the upload process
  73. function startUpload() {
  74. totalUploaded = filesUploaded = 0;
  75. uploadNext();
  76. }
  77. //Event listeners for button clicks
  78. window.onload = function() {
  79. document.getElementById('files').addEventListener('change', onFileSelect, false);
  80. document.getElementById('uploadButton').addEventListener('click', startUpload, false);
  81. }
  82. </script>
  83. </head>
  84. <body>
  85. <div style="width:55%">
  86. <h1>HTML5 Ajax Multi-file Upload With Progress Bar</h1>
  87. <div id='progressBar' style='height: 20px; border: 2px solid green; margin-bottom: 20px'>
  88. <div id='bar' style='height: 100%; background: #33dd33; width: 0%'>
  89. </div>
  90. </div>
  91. <form style="margin-bottom: 20px">
  92. <input type="file" id="files" multiple style="margin-bottom: 20px"/><br/>
  93. <output id="selectedFiles"></output>
  94. <input id="uploadButton" type="button" value="Upload" style="margin-top: 20px"/>
  95. </form>
  96. <div id='debug' style='height: 100px; border: 2px solid #ccc; overflow: auto'></div>
  97. </div>
  98. </body>
  99. </html>

2. 讨论上传进度功能

上面的代码足以说明问题,您在理解上应该不会遇到任何问题。 但是,让我们总结一下要点:

  1. “上传” 按钮不是提交按钮。 因此,单击它不会提交包含表单。 实际上,该脚本使用XMLHttpRequest对象进行上传。
  2. totalFileLength变量保存要上传的文件的总长度。 totalUploaded是到目前为止已上传的字节数。 fileCount包含要上传的文件数,filesUploaded指示已上传的文件数。
  3. window.onload()使用onFileSelect功能映射文件输入元素的更改事件,并使用startUpload映射按钮的单击事件。
  4. 当用户单击“上传”按钮时,将调用startUpload函数,然后依次调用uploadNext函数。 uploadNext上传所选文件集中的下一个文件。 首先创建一个XMLHttpRequest对象和一个FormData对象,接下来要上载的文件将附加到该对象。
  5. 然后,uploadNext函数将XMLHttpRequest对象的进度事件附加到onUploadProgressload事件,并将error事件附加到onUploadCompleteonUploadFailed
  6. 在上载进度期间,会反复调用onUploadProgress功能,从而有机会更新进度条。
  7. 上载完成后,将调用onUploadComplete函数。

3. 多个文件上传控制器和模型类

Spring MVC 文件上传控制器和模型类如下所示:

3.1. Spring MVC 多文件上传控制器

DemoProductController.java

  1. package com.howtodoinjava.demo.controller;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import javax.servlet.http.HttpServletRequest;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.validation.BindingResult;
  8. import org.springframework.web.bind.annotation.ModelAttribute;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.multipart.MultipartFile;
  11. import com.howtodoinjava.demo.model.UploadedFile;
  12. @Controller
  13. public class DemoProductController
  14. {
  15. @RequestMapping("/save-product")
  16. public void saveFile(HttpServletRequest servletRequest,
  17. @ModelAttribute UploadedFile uploadedFile,
  18. BindingResult bindingResult, Model model) {
  19. MultipartFile multipartFile = uploadedFile.getMultipartFile();
  20. String fileName = multipartFile.getOriginalFilename();
  21. try {
  22. File file = new File(servletRequest.getServletContext().getRealPath("/image"), fileName);
  23. multipartFile.transferTo(file);
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. @RequestMapping(value = "/product-input-form")
  29. public String inputProduct(Model model) {
  30. return "productForm";
  31. }
  32. }

3.2. Spring MVC 多文件模型类

UploadedFile.java

  1. package com.howtodoinjava.demo.model;
  2. import org.springframework.web.multipart.MultipartFile;
  3. public class UploadedFile {
  4. private static final long serialVersionUID = 1L;
  5. private MultipartFile multipartFile;
  6. public MultipartFile getMultipartFile() {
  7. return multipartFile;
  8. }
  9. public void setMultipartFile(MultipartFile multipartFile) {
  10. this.multipartFile = multipartFile;
  11. }
  12. }

4. 用于构建示例的其他文件

4.1. web.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="3.1"
  3. xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  6. http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
  7. <display-name>Spring Web MVC Hello World Application</display-name>
  8. <servlet>
  9. <servlet-name>spring</servlet-name>
  10. <servlet-class>
  11. org.springframework.web.servlet.DispatcherServlet
  12. </servlet-class>
  13. <multipart-config>
  14. <max-file-size>20848820</max-file-size>
  15. <max-request-size>418018841</max-request-size>
  16. <file-size-threshold>1048576</file-size-threshold>
  17. </multipart-config>
  18. </servlet>
  19. <servlet-mapping>
  20. <servlet-name>spring</servlet-name>
  21. <url-pattern>/</url-pattern>
  22. </servlet-mapping>
  23. </web-app>

4.2. spring-servlet.xml

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. 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"
  3. xsi:schemaLocation="http://www.springframework.org/schema/beans
  4. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  5. http://www.springframework.org/schema/context/
  6. http://www.springframework.org/schema/context/spring-context-3.0.xsd
  7. http://www.springframework.org/schema/mvc
  8. http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
  9. <context:component-scan base-package="com.howtodoinjava.demo" />
  10. <mvc:resources mapping="/image/**" location="/image/" />
  11. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
  12. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
  13. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  14. <property name="prefix" value="/WEB-INF/views/" />
  15. <property name="suffix" value=".jsp" />
  16. </bean>
  17. <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
  18. <property name="basename" value="messages" />
  19. </bean>
  20. <bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></bean>
  21. </beans>

5. Spring MVC 多个文件上传,带有进度条演示

  • 点击 URL: http://localhost:8080/springmvcexample/product-input-form
    下面的屏幕将在浏览器上加载。
    Spring MVC 在 ajax 和 jquery 中使用进度条上传多个文件 - 图1
    带有进度条的多文件上传 - 输入表单

  • 选择文件,然后单击上载按钮

  • 如果一切正常,那么您将获得如下所示的上传进度栏和上传的文件信息。
    Spring MVC 在 ajax 和 jquery 中使用进度条上传多个文件 - 图2
    带有进度条的多文件上传 - 上传成功

请给我发送有关 Spring mvc 多文件上传的问题和问题,并提供进度条示例

学习愉快!