一、准备好form表单,代码如下:
<form action="/App/upload/uploadfile?name='22.jpg'" method="post" target="id_iframe" enctype="multipart/form-data">
<p><input type="file" name="myfile" value="浏览文件"></p>
<p><input type="submit" value="上传"></p>
</form>
<iframe id="id_iframe" name="id_iframe" style="display:none"></iframe>
1. App是应用的根目录,upload/uploadfile是服务端映射路径。
2. form表单提交类型一定要加上enctype="multipart/form-data",这是提交媒体文件的声明。
3. form表单提交的target="id_iframe",是为后台处理完成后返回结果刷新name为id_iframe的iframe。这样就不会刷新当前页面。
二、后台controller接收请求,代码如下:
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value="/upload")
public class UploadController {
static Logger logger = Logger.getLogger(UploadController.class);
@RequestMapping(value="/uploadfile",method = RequestMethod.POST)
@ResponseBody
public String uploadFile(HttpServletRequest request){
try{
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
logger.info("命中目标1:"+isMultipart);
logger.info("文件名:"+request.getParameter("name"));
if(isMultipart){
String fileName = request.getParameter("name");
FileItemFactory factory = new DiskFileItemFactory();
//ServletFileUpload对象的创建需要依赖FileItemFactory工厂将获得的上传文件FileItem对象保存至服务器硬盘,即DiskFileItem对象
ServletFileUpload upload = new ServletFileUpload(factory);
//设置允许上传的最大文件大小 4M
upload.setSizeMax(4*1024*1024);
//解析http请求消息头
List<FileItem> fileItems = upload.parseRequest(new ServletRequestContext(request));
Iterator iter = fileItems.iterator();
//要执行while内逻辑,需在bean文件中有相应配置,后面会有说明。
while(iter.hasNext()){
FileItem item = (FileItem)iter.next();
if(item.isFormField()){
System.out.println("处理表单内容");
processFormField(item,fileName);
}else{
System.out.println("处理上传文件");
processUploadFile(item,fileName);
}
}
}
return "upload file ok";
}catch(Exception e){
System.out.println("使用 fileupload 包时发生异常 ...");
e.printStackTrace();
return "upload file error";
}
}
public void processFormField(FileItem item, String fileName) {
String name = item.getFieldName();
String value = item.getString();
logger.info("表单域名为:" + name + "值为:" + value);
}
public void processUploadFile(FileItem item, String fileName){
String filename = null;
//获得文件名,此文件名包含路径
if(fileName!=null){
filename = fileName;
}else{
filename = item.getName();
}
logger.info("文件名:"+filename);
if(filename!=null){
File file = new File(filename);
logger.info("创建文件对象File:"+file);
String path = "/home/weblogic/";
//判断路径是否存在
File dirFile = new File(path);
if(!dirFile.exists()){
dirFile.mkdirs();
}
File filetoserver = new File(path,file.getName());
try{
item.write(filetoserver);
}catch(Exception e){
logger.info("文件上传服务器,写入异常");
e.printStackTrace();
}
logger.info("文件:" + filetoserver.getName() + "上传成功");
}else{
logger.info("文件上传失败");
}
}
}
在此,文件上传的实现,使用的是apache的ServletFileUpload,如果同时使用MultipartResolver 和ServletFileUpload,就会在iter.hasNext()返回false,然后整个循环就跳不出去了。整个问题产生的原因是Spring框架先调用了MultipartResolver 来处理http multi-part的请求。这里http multipart的请求已经消耗掉。后面又交给ServletFileUpload ,那么ServletFileUpload 就获取不到相应的multi-part请求。解决方法是加入multipartResolver来单独处理某些请求。
package com.util;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
/**
* @author yawenchen
* 解决:Spring MultipartResolver 或者 ServletFileUpload 冲突导致获取不到http数据/Multipart数据为空
*/
public class MyMultipartResolver extends CommonsMultipartResolver{
private String excludeUrls;
private String[] excludeUrlArray;
public String getExcludeUrls() {
return excludeUrls;
}
public void setExcludeUrls(String excludeUrls) {
this.excludeUrls = excludeUrls;
this.excludeUrlArray = excludeUrls.split(",");
}
/**
* 这里是处理Multipart http的方法。如果这个返回值为true,那么Multipart http body就会MyMultipartResolver 消耗掉.如果这里返回false
* 那么就会交给后面的自己写的处理函数处理例如刚才ServletFileUpload 所在的函数
* @see org.springframework.web.multipart.commons.CommonsMultipartResolver#isMultipart(javax.servlet.http.HttpServletRequest)
*/
@Override
public boolean isMultipart(HttpServletRequest request) {
for (String url: excludeUrlArray) {
// 这里可以自己换判断
if (request.getRequestURI().contains(url)) {
return false;
}
}
return super.isMultipart(request);
}
}
三、在web.xml中这样配置
<bean id="multipartResolver" class="com.util.MyMultipartResolver">
<property name="excludeUrls" value="uploadfile"/>
<!-- url中带有uploadfile的http请求就不会被multipartResolver先解析-->
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
<property name="maxUploadSize">
<value>104857600</value><!-- 上传文件大小限制为31M,31*1024*1024 -->
</property>
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>