标签:style blog http io ar color os 使用 sp
搞JavaWEB的应该或多或少都做过文件上传,之前也做过简单的上传,但是如下的需求也确实把我为难了一把:
1、上传需要异步,
2、需要把上传后文件的地址返回来,
3、需要进度条显示上传进度.
项目使用SpringMVC架构+easyUI,初步分析,进度条可以使用easyui自带的进度条,上传可以使用ajaxFileUpload或者ajaxForm。文件传上去,然后把路径带回来是没问题的,关键是上传进度怎么获取。最终,两种方式都实现啦。
首先,不管哪种方式,后台对文件处理都是必须的。文件处理:
1 /** 2 * 文件上传处理方法 3 * @param fileType 上传文件的类型 4 * @param file 上传的文件 5 */ 6 @RequestMapping("file/uploadFile") 7 public void uploadVideo(int fileType,MultipartFile file) { 8 Map<String, Object> map = new HashMap<String,Object>(); 9 map.put("status", "error"); 10 try { 11 if (file.getSize() > 500 * 1024 * 1024) { 12 map.put("status", "size_err"); 13 }else if(file!=null){ 14 String suffix=file.getOriginalFilename().toLowerCase(); 15 suffix = suffix.substring(suffix.lastIndexOf(".")); 16 String fileDir = "upload/"; 17 switch (fileType) { 18 case 1: 19 fileDir += "video/";//视频文件 20 break; 21 case 2: 22 fileDir += "picture/";//图片文件 23 break; 24 default: 25 break; 26 } 27 String fileName=fileDir+UUID.randomUUID()+suffix; 28 File newFile=newFile(Constant.WEB_ROOT_PATH+ fileName); 29 File dir = newFile.getParentFile(); 30 if (!dir.isDirectory()) { 31 dir.mkdirs(); 32 } 33 //自定义fileCopy方法 34 FileCopyUtils.copy(file.getBytes(),newFile); 35 map.put("data", Config.get().getDomain()+fileName); 36 session.setAttribute("read",100);//稍后进度条用到 37 map.put("status", "success"); 38 } 39 } catch (Exception e) { 40 e.printStackTrace(); 41 } finally{ 42 outJSON(map); 43 } 44 }
方式一 使用ajaxFileUpload:
1.重写CommonsMultipartResolver以监听文件上传进度:
1 /** 2 * 重写CommonsMultipartResolver以监听文件上传进度 3 */ 4 public class PJCommonsMultipartResolver extends CommonsMultipartResolver { 5 private HttpServletRequest request; 6 protected FileUpload newFileUpload(FileItemFactory fileItemFactory) { 7 ServletFileUpload upload=new ServletFileUpload(fileItemFactory); 8 upload.setSizeMax(-1); 9 if (request != null) { 10 HttpSession session = request.getSession(); 11 PJProgressListener uploadProgressListener=new PJProgressListener(session); 12 upload.setProgressListener(uploadProgressListener); 13 } 14 return upload; 15 } 16 17 public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException { 18 this.request = request;// 获取到request,要用到session 19 return super.resolveMultipart(request); 20 } 21 @SuppressWarnings("unchecked") 22 @Override 23 public MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { 24 HttpSession session = request.getSession(); 25 String encoding = "utf-8"; 26 FileUpload fileUpload = prepareFileUpload(encoding); 27 PJProgressListener uploadProgressListener = new PJProgressListener(session); 28 fileUpload.setProgressListener(uploadProgressListener); 29 try { 30 @SuppressWarnings("rawtypes") 31 List fileItems = ((ServletFileUpload) fileUpload).parseRequest(request); 32 return parseFileItems(fileItems, encoding); 33 } catch (FileUploadBase.SizeLimitExceededException ex) { 34 throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); 35 } catch (FileUploadException ex) { 36 throw new MultipartException("Could not parse multipart servlet request", ex); 37 } 38 }
2.实现进度监听接口:
1 public class PJProgressListener implements ProgressListener { 2 private HttpSession session; 3 public PJProgressListener() { 4 } 5 public PJProgressListener(HttpSession _session) { 6 session = _session; 7 ProgressEntity ps = new ProgressEntity(); 8 session.setAttribute("upload_ps", ps); 9 } 10 public void update(long pBytesRead, long pContentLength, int pItems) { 11 ProgressEntity ps = (ProgressEntity) session.getAttribute("upload_ps"); 12 ps.setpBytesRead(pBytesRead); 13 ps.setpContentLength(pContentLength); 14 ps.setpItems(pItems); 15 double mBytes = pBytesRead; 16 double total = pContentLength; 17 if (total <= 0) 18 return; 19 double read = (mBytes / total); 20 read = read * 98; 21 DecimalFormat df = new DecimalFormat("#"); 22 Integer result = Integer.parseInt(df.format(read)); 23 //更新上传进度 24 session.setAttribute("read",result ); 25 } 26 27 /** 28 * 文件上传进度信息 29 * 30 * @author Van 31 * 32 */ 33 public class ProgressEntity { 34 private long pBytesRead = 0L; 35 private long pContentLength = 0L; 36 private int pItems; 37 38 public long getpBytesRead() { 39 return pBytesRead; 40 } 41 42 public void setpBytesRead(long pBytesRead) { 43 this.pBytesRead = pBytesRead; 44 } 45 46 public long getpContentLength() { 47 return pContentLength; 48 } 49 50 public void setpContentLength(long pContentLength) { 51 this.pContentLength = pContentLength; 52 } 53 54 public int getpItems() { 55 return pItems; 56 } 57 58 public void setpItems(int pItems) { 59 this.pItems = pItems; 60 } 61 62 @Override 63 public String toString() { 64 return "ProgressEntity [pBytesRead=" + pBytesRead + ", pContentLength=" + pContentLength + ", pItems=" + pItems + "]"; 65 } 66 } 67 68 }
3.修改springMVC默认的CommonsMultipartResolver为自定义的:
1 <bean id="multipartResolver" 2 class="cn.bluemobi.util.fileUplaod.PJCommonsMultipartResolver"> 3 <property name="maxUploadSize" value="2147483648" /> 4 <property name="maxInMemorySize" value="4096" /> 5 </bean>
4.写一个接口读取session里更新的文件上传进度:
1 /** 2 * 前台获取进度方法 3 */ 4 @RequestMapping("file/getUploadProgress") 5 public void getFileUplaodPreogress(){ 6 Map<String, Object> map = new HashMap<String, Object>(); 7 try { 8 Integer pre = (Integer) session.getAttribute("read"); 9 map.put(DATA, pre); 10 } catch (Exception e) { 11 e.printStackTrace(); 12 } finally{ 13 outJSON(map); 14 } 15 }
5.页面上传进度显示:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!DOCTYPE html> 3 <html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta charset="UTF-8"> 6 <title>上传文件</title> 7 <link id="easyuiTheme" rel="stylesheet" href="resource/js/jquery-easyui-1.3.5/themes/default/easyui.css" type="text/css"/> 8 <link type="text/css" rel="stylesheet" href="resource/css/icon.css"/> 9 <link rel="stylesheet" type="text/css" href="resource/css/basic.css"/> 10 <script src="resource/jquery-1.7.2.min.js" type="text/javascript"></script> 11 <script type="text/javascript" src="resource/js/jquery.easyui.min.js"></script> 12 <script type="text/javascript" src="resource/js/easyui-lang-zh_CN.js"></script> 13 <script type="text/javascript" src="resource/js/ajaxfileupload.js"></script> 14 </head> 15 <body class="easyui-layout"> 16 <div align="left" data-options="region:‘center‘,border:false" style="padding-left:20px;padding-right:20px;"> 17 <table width="500" border="0" align="center" cellpadding="1" cellspacing="1"> 18 <tr> 19 <td nowrap align="right">上传文件:</td> 20 <td align="left"> 21 <input type="file" id="file" name="file" style="width: 150px;" onchange="ajaxFileUpload()"> 22 <span id="add_span_video" style="width:250px;color:red;"></span> 23 </td> 24 </tr> 25 <tr> 26 <td align="right">上传地址:</td> 27 <td align="left"><input id="fileSrc" type="text" style="width:450px;"/></td> 28 </tr> 29 </table> 30 </div> 31 32 <!-- 进度条框框 --> 33 <div id="progressBar_dialog" class="easyui-dialog" title="上传进度"> 34 <table style="padding: 5px;padding-top: 10px;" cellspacing="0" cellpadding="0" border="0"> 35 <tr> 36 <td> 37 <div id="progressNumber" class="easyui-progressbar" style="width: 400px;"></div> 38 </td> 39 </tr> 40 </table> 41 </div> 42 43 44 <script type="text/javascript"> 45 //文件上传 46 var intel; 47 function ajaxFileUpload() { 48 //打开上传进度条的dialog 49 $(‘#progressBar_dialog‘).dialog({ 50 closed : false 51 }); 52 //打开定时器,获取文件上传进度 53 intel = window.setInterval("getPro()", 100); 54 55 //开始上传 56 $.ajaxFileUpload({ 57 url:‘fileadmin/uploadVideo.htm‘, //需要链接到服务器地址 58 secureuri : false, 59 fileElementId : ‘file‘, //文件选择框的name和id属性 60 dataType : ‘json‘, //服务器返回的格式,可以是json 61 data:{fileType:1}, 62 success : function(data) { //相当于java中try语句块的用法 63 data = data.replace(/<[^>].*?>/g, "");//对返回的数据进行转换 64 data = eval("(" + data + ")");//对返回的数据进行转换 65 var src = data.data; 66 $("#fileSrc").val(src); 67 $.message.alert("提示","上传成功!"); 68 } 69 }); 70 } 71 72 //读取进度条信息 73 function getPro() { 74 $.ajax({ 75 type : "post", 76 url :‘file/getUploadProgress.htm‘, 77 success : function(msg) { 78 msg = msg.replace(/<[^>].*?>/g, "");//对返回的数据进行转换 79 msg = eval("(" + msg + ")");//对返回的数据进行转换 80 var data = msg.data; 81 $(‘#progressNumber‘).progressbar(‘setValue‘, Math.floor(data)); 82 if (Math.floor(data) == 100) { 83 $(‘#progressBar_dialog‘).dialog({ 84 closed : true 85 }); 86 window.clearInterval(intel); 87 } 88 } 89 }); 90 } 91 92 $(function() { 93 //进度条对话框初始化 94 $(‘#progressBar_dialog‘).dialog({ 95 title : ‘上传进度‘, 96 width : 460, 97 height : 80, 98 closed : true, 99 cache : false, 100 modal : true, 101 closable : false, 102 resizable : false, 103 }); 104 }); 105 106 </script> 107 </body> 108 </html>
这种方式是我最初想到和做出来的,内网测试上传图片等小文件没有问题,但是上传了一个1G多大的文件的时候就出现问题啦。文件上传成功,进度条也正常显示了,上传后的文件路径也返回了,但是在页面没有接收到返回的路径。究其原因,是因为页面开了两个ajax同时请求,然后返回结果冲突了。几经周折,于是乎又寻求到了如下的第二种方式。
方式二 使用ajaxForm:
只有一个步骤:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!DOCTYPE html> 3 <html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta charset="UTF-8"> 6 <title>上传文件</title> 7 <link id="easyuiTheme" rel="stylesheet" 8 href="resource/js/jquery-easyui-1.3.5/themes/default/easyui.css" 9 type="text/css" /> 10 <link type="text/css" rel="stylesheet" href="resource/css/icon.css" /> 11 <link rel="stylesheet" type="text/css" href="resource/css/basic.css" /> 12 <script src="resource/jquery-1.7.2.min.js" type="text/javascript"></script> 13 <script type="text/javascript" src="resource/js/jquery.easyui.min.js"></script> 14 <script type="text/javascript" src="resource/js/easyui-lang-zh_CN.js"></script> 15 <script type="text/javascript" src="resource/js/ajaxfileupload.js"></script> 16 </head> 17 <body class="easyui-layout"> 18 <div align="left" data-options="region:‘center‘,border:false" 19 style="padding-left: 20px; padding-right: 20px;"> 20 <form id="fileForm" action="file/uploadFile.htm?fileType=2" 21 method="post" enctype="multipart/form-data"> 22 <div> 23 <input id="img" name="file" type="file" onchange="doSubmit(this)"> 24 <input id="fileUrl" type="text"> 25 </div> 26 </form> 27 </div> 28 29 <!-- 进度条框框 --> 30 <div id="progressBar_dialog" class="easyui-dialog" title="上传进度"> 31 <table style="padding: 5px; padding-top: 10px;" cellspacing="0" cellpadding="0" border="0"> 32 <tr> 33 <td> 34 <div id="progressNumber" class="easyui-progressbar" style="width: 400px;"></div> 35 </td> 36 </tr> 37 </table> 38 </div> 39 40 <script type="text/javascript"> 41 var fileId; 42 function doSubmit(target){ 43 fileId = $(target).attr("id"); 44 $("#fileForm").submit(); 45 } 46 $(function() { 47 //进度条对话框初始化 48 $(‘#progressBar_dialog‘).dialog({ 49 title : ‘上传进度‘, 50 width : 460, 51 height : 80, 52 closed : true, 53 cache : false, 54 modal : true, 55 closable : false, 56 resizable : false 57 }); 58 59 $("#fileForm").ajaxForm({ 60 dataType : "json", 61 beforeSend : function() {//上传之前设置,在这里可以写验证 62 $(‘#progressBar_dialog‘).dialog({ 63 closed : false 64 }); 65 }, 66 uploadProgress : function(event, position, total, 67 percentComplete) {//进度条 68 $(‘#progressNumber‘).progressbar(‘setValue‘, 69 percentComplete); 70 }, 71 success : function(data) {//成功之后执行 72 var fileInput = $("#" + fileId); 73 fileInput.after(fileInput.clone().val("")); 74 fileInput.remove(); 75 $("#fileUrl").val(data.data); 76 }, 77 complete : function(data) { 78 $(‘#progressBar_dialog‘).dialog({ 79 closed : true 80 }); 81 } 82 }); 83 }); 84 </script> 85 </body> 86 </html>
个人认为第二种方式简单轻便,不需要在后台写监听,更改配置文件,更不需要自己开启网页定时器了,比较喜欢。
标签:style blog http io ar color os 使用 sp
原文地址:http://www.cnblogs.com/shyma/p/4148293.html