1. 页面使用Jquery ajaxfileupload插件的实现的基础上(见WEB文件上传之JQuery ajaxfileupload插件使用(二)),服务器端结合采用springMVC来实现
2. 实现技术点:
springMVC中正常处理时JSON数据的返回
springMVC中异常统一拦截处理时JSON数据的返回
springMVC中文件上传进度监听的实现
3. 具体实现:
UploadController.java
package com.test.controller; import java.io.File; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.commons.CommonsMultipartFile; import com.test.servlet.NoSupportExtensionException; import com.test.servlet.State; @Controller @RequestMapping(value = "/mvc") public class UploadController { /** 日志对象*/ private Log logger = LogFactory.getLog(this.getClass()); private static final long serialVersionUID = 1L; /** 上传目录名*/ private static final String uploadFolderName = "uploadFiles"; /** 允许上传的扩展名*/ private static final String [] extensionPermit = {"txt", "xls", "zip"}; @RequestMapping(value = "/upload.do", method = RequestMethod.POST) public @ResponseBody Map<String, Object> fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpSession session, HttpServletRequest request, HttpServletResponse response) throws Exception{ logger.info("UploadController#fileUpload() start"); //清除上次上传进度信息 String curProjectPath = session.getServletContext().getRealPath("/"); String saveDirectoryPath = curProjectPath + "/" + uploadFolderName; File saveDirectory = new File(saveDirectoryPath); logger.debug("Project real path [" + saveDirectory.getAbsolutePath() + "]"); // 判断文件是否存在 if (!file.isEmpty()) { String fileName = file.getOriginalFilename(); String fileExtension = FilenameUtils.getExtension(fileName); if(!ArrayUtils.contains(extensionPermit, fileExtension)) { throw new NoSupportExtensionException("No Support extension."); } file.transferTo(new File(saveDirectory, fileName)); } logger.info("UploadController#fileUpload() end"); return State.OK.toMap(); } }
自定义CommonsMultipartResolver类
CustomCommonsMultipartResolver.java
package com.test.controller; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUpload; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import com.test.servlet.FileProcessListener; public class CustomCommonsMultipartResolver extends CommonsMultipartResolver { @Override protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); // 加入文件进度监听器 (原Source上添加) start FileProcessListener processListener = new FileProcessListener( request.getSession()); fileUpload.setProgressListener(processListener); // 加入文件进度监听器 (原Source上添加) end try { List<FileItem> fileItems = ((ServletFileUpload) fileUpload) .parseRequest(request); return parseFileItems(fileItems, encoding); } catch (FileUploadBase.SizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); } catch (FileUploadException ex) { throw new MultipartException( "Could not parse multipart servlet request", ex); } } }
统一异常处理类
package com.test.controller; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.core.Ordered; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import com.test.servlet.NoSupportExtensionException; import com.test.servlet.State; public class ExceptionHandler implements HandlerExceptionResolver, Ordered { private Log logger = LogFactory.getLog(this.getClass()); public int getOrder() { return Integer.MIN_VALUE; } public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { logger.info("ExceptionHandler#resolveException() start"); Map<String, Object> errorMap = null; if(ex instanceof NoSupportExtensionException) { errorMap = State.NO_SUPPORT_EXTENSION.toMap(); } else if(ex instanceof MaxUploadSizeExceededException){ //spring 中对apache common组件中抛出的FileSizeLimitExceededException做了转换 errorMap = State.OVER_FILE_LIMIT.toMap(); } else { errorMap = State.ERROR.toMap(); } //这里牵扯到spring mvc的异常处理,这里暂时做一个简单处理,不做深究 try { ObjectMapper objectMapper = new ObjectMapper(); response.setContentType("text/html;charset=UTF-8"); JsonGenerator jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(response.getOutputStream(), JsonEncoding.UTF8); objectMapper.writeValue(jsonGenerator, errorMap); } catch(Exception e) { logger.error(e.getMessage(), e); } logger.info("ExceptionHandler#resolveException() end"); return null; } }
spring-context.xml配置
<?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:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- configure the annotation scan base package --> <context:component-scan base-package="com.test.controller" /> <!-- open MVC annotation function --> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!-- define the exception interceptor--> <bean class="com.test.controller.ExceptionHandler" /> <!-- define the upload config --> <bean id="multipartResolver" class="com.test.controller.CustomCommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8" /> <property name="maxUploadSize" value="31457280" /> <property name="maxInMemorySize" value="40960" /> <property name="uploadTempDir" value="tempFiles" /> </bean> </beans>
web.xml配置
<!-- spring context配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 编码过滤器配置 --> <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> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring mvc 配置 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextAttribute</param-name> <param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet>
4. 总结
实现过程中遇到的问题
问题1:ajaxfileupload插件是通过监听iframe的onload事件类实现文件上传的无刷新异步上传,实际就是在onload触发时获取iframe的body体中的文本,在响应头的content-Type为application/json的时候会出错,chrome/firefox的情况下会出现iframe获取出的json文本出现前后加入<pre></pre>标签的情况,导致ajaxfileupload插件解析json数据出错,原因应该是chrome/firefox浏览器处理content-Type为applicatioin/json自动做了html的转换,所以自动加入了pre标签。而在IE浏览器下,直接不支持content-Type为application/json的情况提示下载文件。
解决:在返回json数据时将响应头content-Type设置为text/html;charset=UTF-8,通过配置spring配置文件实现
<mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
结论:ajaxfileupload插件只支持content-Type=text/html的响应头,进行数据返回。
问题2:@ResponseBody注解只能针对正常处理时的json数据返回,异常处理时无作用
解决: 通过自定义HandlerExceptionResolver类解决,不过这里的解决方案不是最佳,无法根据是否使用@ResponseBody动态变化是否返回JSON数据
问题3: springMVC文件上传进度监听器没有默认的实现
解决: 直接使用apache common的文件上传进度监听接口,并通过重写CommonsMultipartResolver类的parseRequest方法进行和Fileupload类进行绑定
Demo源码见附件
相关推荐
其次,ajaxfileupload.js是前端用于异步文件上传的JavaScript库。这个库允许用户在不刷新整个页面的情况下,通过Ajax技术与服务器进行交互,上传文件。这样可以提供更好的用户体验,因为用户可以继续浏览页面,而...
在构建Web应用时,文件上传是一项常见的功能,尤其是在使用SpringMVC作为后端框架和EasyUI作为前端组件库的情况下。本篇文章将详细讲解如何利用EasyUI的`$.ajaxFileUpload`插件与SpringMVC结合,实现无刷新的文件...
在现代Web应用中,文件上传是一项常见的功能,尤其是在企业级应用中。本示例将探讨如何结合Spring MVC和Ajax技术实现一个支持文本域和文件域的表单上传功能,同时利用ajaxfileupload.js插件来优化用户体验。让我们...
在本文中,我们将深入探讨如何使用Spring MVC与Ajax实现异步文件上传,这是一项常见的Web开发任务,可以显著提升用户体验。我们将关注以下关键知识点: 1. **Spring MVC**:Spring MVC是Spring框架的一个模块,用于...
在本文中,我们将深入探讨如何使用`ajaxFileUpload`与`Spring MVC`框架结合实现异步文件上传功能。`ajaxFileUpload`是一个基于JavaScript的插件,它允许我们使用Ajax技术进行文件上传,无需刷新页面,提高用户体验。...
SpringMVC作为流行的Java Web框架,提供了强大的支持来处理文件上传。本文将详细介绍如何利用SpringMVC与ajaxfileupload插件配合,实现无刷新的文件上传。 **一、ajaxfileupload介绍** ajaxfileupload是基于jQuery...
本文将详细介绍如何结合 `AjaxFileUpload` 和 `SpringMVC` 实现文件上传。 ### 1. 引入库和配置 首先,确保在项目中引入了jQuery库以及`AjaxFileUpload.js`。在JSP页面中,可以使用以下代码引入这些文件: ```...
这篇博客"springmvc入门基础之文件上传"显然会讲解如何在Spring MVC应用中实现这一功能。我们将探讨相关的关键知识点,包括Spring MVC的MultipartFile接口、前端表单处理以及后台控制器的配置。 首先,`...
同时,ajax并不支持文件的上传,此时ajaxfileupload就应运而生了,本人,在此基础上经过改写,使其同时支持,多文件上传isMore(boolen)、序列化类型参数ContentType(Serial/json)’,并且给出了SpringMVC的文件...
同时,AjaxFileupload组件可以用来实现文件上传功能,实现异步文件上传而不刷新页面。 电子邮件的发送功能在许多应用场景中也是必要的。可以使用Java Mail API来实现邮件的发送功能,需要了解如何配置邮件服务器,...
接着,我们需要在Spring MVC的配置文件(如:springMVC.xml)中配置多部分解析器(MultipartResolver),以支持文件上传。这里我们使用的是CommonsMultipartResolver,设置最大上传文件大小为10MB。 ```xml ...