Web开发中的文件上传问题研究

前因:因为web开发用到文件上传功能,搜索到了Valums,感觉很不错,特别是它在非IE浏览器下通过HTML5技术来支持多文件上传,支持拖拽功能等,不过在具体用中并不顺利,Valums在FF下罢工,追究原因,原来跟我使用Aapche FIleUpload有关,再追究,对文件上传的原理有了新的认识。

1. 文件上传时的抓包

不说理论,先看下对一个基于WEB的文件上传的抓包。在IE7/8下(不要用firefox或者chrome),在http://valums.com/ajax-upload/页面上,上传一个文件,用wireshark抓包,结果如下:

sshot-2

众所周知,一个HTTP报文主要请求行、请求头部、空行和请求数据四部分组成,而对于文件上传来说,对应的HTTP报文的关键设置有:

  • 请求行设置为POST方式
  • 请求头部设置Content-Length,设置为要传输的文件长度
  • 请求头部设置Content-Type:  multipart/form-data;   boundary=---------------------------88739631214394723612117964652, 这个boundary是用来作为多个上传文件的分割的。
  • 请求数据部分,每个部分(包括文件和form内的html标签等)的结构大致如下:

 

 

之所以在这儿提到抓包,是因为Apache FileUpload库就是为这种格式的报文设计的,它的ServletFileUpload.isMultipartContent()方法,还有它常规的fileItem的遍历操作都是建立在报文合乎上面格式的前提下才能正常使用。之前我并不清楚,后来在客户端使用Valums库出错的时候才慢慢注意到这些问题的。

2. 传统的解决方案

传统的web页面上的文件上传是通过html标签来实现的:

 

当你在页面上提交这样的form时,浏览器器会为你自动生成1.中那样格式的报文。本方式最大的缺点是提交就要刷新页面,于是,见下面。。。

3. 异步提交的文件上传

因为ajax技术的引进,人们也希望文件上传做成异步的,在页面后台进行,而不用刷新整个页面。gmail,QQ等纷纷采用flash技术,不过我还是想用纯粹的js来解决这个问题。根据http://valums.com/ajax-upload/的思路,方法有两种,一是在IE中使用隐藏的ifram+加异步form提交,二是在FF或者Chrome中利用xhr + html5特性。

iframe+form异步提交很简单,在网页动态增加一个iframe,在iframe里动态增加一个带有属性enctype="multipart/form-data"的form,然后异步提交这个form即可。

第二种方法,主要是利用XmlHttpRequest(简称XHR)技术来完成,具体实现上,可以利用Chrome等提供的FormData或者FileAPI,也可以只简单地使用XHR来完成(这种方法有缺陷,当后台使用Apache的Commons upload库时,就会发现)。

4. Valums插件的问题与解决方案

XHR是Ajax的核心类。我们可以用它来进行异步通信,包括异步发送文件。Valums在Firefox和Chrome上关于文件上传的实现很简单,核心代码如下:

 

 

不过,这种作法有个问题,当后台使用Apache FileUpload库的时候出现。在1.中已经提到过Valums在IE下通过IFRAME异步上传文件时的抓包;现在对Valums在Chrome下进行抓包,发现包的数据部分不一样,

sshot-1

很明显,这个包与前面在IE下的抓包有两处的关键不同,一是Content-Type没有关于文件上传的设置;二是请求数据部分的组成不同。这样的结果导致在后台用Apache FileUpload处理文件的时候无法识别(FileUpload的用法见参考4)。解决办法有两种,一种是在客户端设置异步请求的Content-Type,并在后台避开FileUpload的常规用法,而直接用操作request.getInputStream,这样的话,既要修改客户端,又要在后台判断不同浏览器然后作出不同应对,不合算;我用另一种方法解决,在客户端对Valums修改,使之与IE下通过IFRAME的请求报文完全相同,这样就不用再改后台了。

具体的作法是利用Chrome和FF所支持的HTML5新特性——FormData。FormData可以生成如1.中提到那样传统的文件上传请求格式,并且你可以自由地在FormData中通过append方法来增加各种key/value对作为参数,附加到请求中。

 

不过,这种解决方案的前提是浏览器支持FormData,IE不要指望了,FF和chrome比较新的应该都支持,具体的版本号我没测试过,反正我机子上的浏览器都可以。

5. 参考:

1. http://hi.baidu.com/netpet/blog/item/423007faa0867f9058ee90c4.html

2. valums文件上传js插件:http://valums.com/ajax-upload/

3. 关于File object: https://developer.mozilla.org/en/Using_files_from_web_applications

4. Apache Fileupload文档:http://commons.apache.org/fileupload/using.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值