免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3601 | 回复: 0
打印 上一主题 下一主题

使用Javascript XMLHttpRequest模拟表单(Form)提交上传文件 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-26 18:14 |只看该作者 |倒序浏览
很长时间没有遇到一个两天两夜调不通的问题了,值得花时间好好总结一下。
客户端用Javascript XMLHttpRequest在Mozilla平台上实现,服务器环境是Tomcat +
Spring,以前实现过多次文件上载功能,但是以前的实现有个特点:要么客户端手工编程,要么服务器侧手工编程,但是从来没有两边都手工编程的。例如,
在客户端,直接用浏览器的Form提交,不用管底层是怎样将文件上传的,如果手工编程的话就需要使用XMLHttpRequest对象模拟浏览器的表单提
交过程。而在服务器测直接使用Spring的
org.springframework.web.servlet.mvc.SimpleFormController类,可以不管Spring是怎样解
析MultipartHttpServletRequest类型的上传请求的,如果是手工编程就需要手工辨别
MultipartHttpServletRequest请求类型,然后调用
MultipartHttpServletRequest.getFileNames()方法将上传的文件名和文件内容分别提取出来进行处理。
此次两边同时手工做,心里没有底,出了问题不知道哪一侧不对。偏偏出了问题, 服务器总是抛出异常
org.apache.commons.fileupload.FileUploadException: Read timed out
实际上在编程之前就心里开始打鼓,因为根据规范,HTTP中传送的内容是ASCII码的,要上传二进制文件,是否要手工将二进制用
7bit编码
?另外,模拟表单提交上传文件都是模拟一个multipart/form-data消息,根据
HTML规范
,使用边界(boundary)字符串将各个字段分割开,上传文件时既有描述边界格式的文本内容,也有二进制文件内容,怎样使用XMLHttpRequest.send()函数发送这种混合的内容?
带着这些问题,先上网找几个例子,先阅读了
XMLHttpRequest模拟表单上传文件
,照着做了出现上述异常,继续网上冲浪,奋战一天多,找了几个好的文章:
一个详细的例子

中文的例子和评论
。异常仍然不能排除,后来将重点放在服务器侧,搜索read timed out有关的内容,很多遇到这样问题的帖子,但是没有一个合适的,后来
在一个论坛帖子
中,有人认为
having trouble streaming the file contents into the multi-part form post
于是将重点再次转回客户端,好像是这个原因,因为如果不用文件streaming(同时使用了nsIStringInputStream,
nsIFileInputStream,
nsIBinaryInputStream,nsIMultiplexInputStream等Mozilla的XPCOM对象),而是直接将内容写入,
是可以的。尝试了无数次,人越着急脑子越不好使,暂时放弃了。因为不是必须实现的功能(在
网页抓取/数据抽取/异构数据对象搜索引擎工具包MetaSeeker V4版本

这是可选功能),放弃后思想没有负担了,今天中午突然想到可能是因为XMLHttpRequest中读了两次文件,而
nsIFileInputStream设定成指针不能回零而且读到EOF就关闭流,所以第二次读时就读超时了。使用
XMLHttpRequest.send()有可能发送两次HTTP消息,因为服务器使用了HTTP
Digest鉴权,所以第一次读文件流时已经读完了,第二次没的读了。下午一试即灵,这才想起
中文的例子和评论
那篇文章,在真正上传文件之前先发一个内容为空的用于鉴权的消息。
主要问题解决了,还有一个小问题,就是上述引用的这些例子都不能在我的环境中用,发上去的消息中无法正确解析出上传的文件来。实际上他们的程序都不符合
HTML规范
,详细说明如下:
在程序中定义了一个变量boundary,大部分例子中这个boundary变量的起始字符是"--",因为在HTTP消息体中要使用"--",但是,如果这样定义,那么调用
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
设置HTTP消息头的时候,就将"--"也声明进去了,我发现在我的运行环境中这样不行,如果定义的变量boundary中没有起始字符"--"就可以了。当然此时要注意在整个消息的结尾需要在boundary字符串前后都加"--",可以参照HTML规范构造符合规范的消息体。难道运行平台不一样使用方法就不一样吗?
另外还有一个疑问,程序运行结束后是否应该将打开的流都调用close()?上面的例子没有一个调用的。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/81110/showart_2060737.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP