文件上传前检测客户端文件大小的三种方法

前段时间,因工作需要,需要在文件上传时限制文件的大小,所以需要在上传之前检测文件的大小。

 

方法一: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异步提交表单的详细介绍,会在下一篇文章中介绍。

这种方法的好处是不受客户端和服务器端的安全性影响,不好的地方是会先进行一个异步提交,需要消耗一定资源,当然因为是异步的,只要不是上传特别大的附件而导致检测过程过长,页面端的响应效果还是没什么太大的影响。

posted @ 2013-12-17 15:58  RyanChan  阅读(13051)  评论(2编辑  收藏  举报