前段時間,因工作需要,需要在文件上傳時限制文件的大小,所以需要在上傳之前檢測文件的大小。
方法一:js檢測文件大小
一開始的想法是通過js直接在前端檢測文件大小,代碼如下:
//獲取上傳文件大小 function getFileSize(filePath) { var vBrowserVersion = getBrowserVersion(); if("MSIE6.0" == vBrowserVersion){//對於IE6,使用Image的fileSize屬性進行判斷文件大小 var image=new Image(); image.dynsrc=filePath; return image.fileSize; }else if(vBrowserVersion.indexOf("MSIE")>=0){//對於IE6以上瀏覽器(IE6是公司默認最低版本),使用ActiveXObject進行上傳 var fso = new ActiveXObject("Scripting.FileSystemObject"); return fso.GetFile(filePath).size; }else{//其它的瀏覽器,也是采用Image的fileSize屬性進行判斷文件大小 var image=new Image(); image.dynsrc = filePath; return image.fileSize; } }
但這種方法存在一些弊端:
1、IE6下面是利用的Image標簽的dynsrc屬性去判斷;
2、IE8下面使用ActiveXObject進行上傳的話,是IE安全機制不支持的,需要降低本地瀏覽器的安全設置,對於開發者來說,是不可能去限制用戶的。
故這種方法不可行。
方法二:java讀取文件流方式
接着的一種做法是通過dwr的方式,將文件路徑傳到后台去,再去讀取文件的大小。代碼如下:
1 /** 2 * 讀取單據所帶的附件總大小 3 * 4 * @param filaPath 准備上傳的文件的路徑 5 * @param moduleKey 文件對象類型 6 * @param moduleObjectId 文件對象ID 7 * @return lAttachmentTotalSize 該單據的附件總大小 8 * @throws AttachmentException 9 */ 10 public static long getAttachmentTotalSize(String filePath, String moduleKey, String moduleObjectId) 11 throws AttachmentException { 12 // 附件總大小 13 long lAttachmentTotalSize = 0; 14 // 准備上傳的文件大小 15 long lAttachmentSize = 0; 16 // 已經保存的附件的大小 17 long lExistAttachmentSize = 0; 18 FileInputStream fis = null; 19 // 根據對象類型和對象ID查詢出已經保存的附件 20 List lstAttachment = queryAttachmentList(moduleKey, moduleObjectId); 21 if (null != lstAttachment && lstAttachment.size() > 0) { 22 for (int i = 0, iSize = lstAttachment.size(); i < iSize; i++) { 23 AttachmentVO vo = (AttachmentVO) lstAttachment.get(i); 24 // 讀取附件的大小,並累加 25 lExistAttachmentSize += vo.getFileSize(); 26 } 27 } 28 // 根據filePath讀取准備上傳的文件大小,與已經保存的文件大小相加 29 try { 30 File ff = new File(filePath); 31 if (ff.exists()) { 32 fis = new FileInputStream(ff); 33 lAttachmentSize = fis.available(); 34 } else { 35 logger.error("AttachmentUtil.getAttachmentTotalSize方法,獲取准備上傳的文件時,文件不存在"); 36 } 37 } catch (IOException ex) { 38 logger.error("AttachmentUtil.getAttachmentTotalSize方法,讀取文件大小時發生異常", ex); 39 } finally { 40 // 關閉流 41 try { 42 if (null != fis) { 43 fis.close(); 44 } 45 } catch (IOException ex) { 46 logger.error("關閉流時發生異常", ex); 47 } 48 } 49 // 附件總大小=已經存在的附件大小+准備上傳的附件大小 50 lAttachmentTotalSize = lExistAttachmentSize + lAttachmentSize; 51 return lAttachmentTotalSize; 52 }
這個方法也存在一些弊端:
1、服務器端在讀取文件路徑時,是訪問不了客戶端的文件的,它只會放在服務器端自己對應路徑下的文件,但往往這個路徑下是不存在對應文件的,故讀取出來的文件大小總為0;
2、IE8下由於安全問題,服務端獲取客戶端文件的路徑,會變為C:/fakePath問題,這個問題在下一篇文章中會有解決方案;
方法三:Ajax異步提交表單獲取文件大小
最后采取的一種方法是,通過Ajax進行異步的表單提交,因為form里面使用了file標簽,是可以拿到文件的大小的。代碼如下:
1 //定義ajax異步提交form時需要的參數 2 var options = { 3 url:'<common:webRoot/>/product/attachment/attachmentMultiAction.do?queryType=getAttachmentTotalSize', 4 success:successReturn, 5 type:'post' 6 }; 7 //ajax異步提交form 8 jQuery("#attachmentForm").ajaxSubmit(options); 9 10 11 12 //ajax返回后回調方法 13 function successReturn(data){ 14 //后台返回的消息固定為FileTooLarge 15 if("FileTooLarge" == data){ 16 var vMessage = "您添加的附件文件總大小超過(<%=AttachmentInfo.ATTACHMENT_SIZE/1024/1024%>M),請壓縮文件或者重新選擇。"; 17 alert(vMessage); 18 }else{//返回消息為空時,則正常提交form,上傳文件 19 document.attachmentForm.target = "_self"; 20 document.attachmentForm.action = "<common:webRoot/>/product/attachment/attachmentMultiAction.do"; 21 document.attachmentForm.submit(); 22 window.loadingImg.style.visibility = "visible"; 23 } 24 }
其中successReturn是返回后調用的方法,如果文件過大則進行提示,否則重新提交,進行上傳。
關於Ajax異步提交表單的詳細介紹,會在下一篇文章中介紹。
這種方法的好處是不受客戶端和服務器端的安全性影響,不好的地方是會先進行一個異步提交,需要消耗一定資源,當然因為是異步的,只要不是上傳特別大的附件而導致檢測過程過長,頁面端的響應效果還是沒什么太大的影響。