• 用xmlhttp将html的数据打包成multipart/formdata格式,实现异步上传文件功能[转]


    阅读本文之前,可以先阅读RFC1867 Form Based File Upload in HTML协议。

    1.
    不知道为什么,在局域网,有些电脑上含有<input type="file>的<form method="post" enctype="multipart/form-data">表单提交时很快,但有些很慢。
    服务器端使用过多种文件接收工具库测试如apache common file upload、jspsmartupload等等亦如此。
    也换过浏览器如IE和FireFox,问题依然。

    在搜索的过程中,有人说这是浏览器的限制,或者是网络问题,或者是服务器网络设定等等,但是... 没有人指出具体的解决方案,><!。
    不过在多次试验下,终于发现,如果是用applet来发送或者是用xmlhttp把表单打包成multipart/form-data格式可以解决这个问题,热泪盈眶中...

    当然事情不是这么顺利。首先我使用applet,但是发现该死的jre安全设定不允许访问本地文件,耗了我很多精力。虽然后来applet成功了,不过设定这么困难,而且还要下载jre,客户肯定不干。

    然后我考虑在浏览器中打包数据,用流发送。首先在一个法国网站找到mozilla/firefox的解决方案,坚定了我的信心。尝试在IE里用Scripting.FileSystemObject和ADODB.Stream发送,但是ADODB.Stream蹩脚的使用方法把我困住,后来,居然在VB论坛找到了正确的api使用方法,然后我把他转成javascript,大功告成。

    接着我想去测试一下firefox下的数据打包发送,安全设置的难度不亚于jre,我投降~~。

    2.
    现在贴一下相关帖子
    最早是在javascript论坛发现此帖,几年前的事了。后来发现他是把二进制编码成String,在服务器端再反编码,太浪费了,而且java方面似乎没什么现成的反编码类库。
    http://community.csdn.net/Expert/topicview.asp?id=1546672

    上文提到的法国网站的帖子,他用的是mozilla的,对IE无用。
    http://xulfr.org/wiki/ApplisWeb/Request

    上文提到的VB论坛的帖子。
    http://community.csdn.net/Expert/topic/4407/4407031.xml?temp=.8799097

    感谢这些技术共享的作者。

    3.
    讲解一下ADODB.Stream的使用特点。
    为了使用ADODB.Stream,客户端IE需要降低浏览器权限,推荐做法是把服务器网址加入到"受信任的站点",再自定义安全级别,将"对没有标记为安全的ActiveX控件进行初始化和脚本运行"设置为"启用"。

    stream = new ActiveXObject('ADODB.Stream');
    stream.Type = 2; // 2代表流的类型为文本
    stream.CharSet = "utf-8";
    stream.Open();
    stream.WriteText("test string");
    // 在写完文本之后,需要写入二进制内容,
    // 这里是一个要点,需要把流的类型改为1,
    // 但是要改变状态,就得把流的位置设置为0
    // 看看下面是怎么作的
    position = stream.Position; // 先记录当前位置
    stream.Position = 0; // 位置设置为0
    stream.Type = 1; // 改变流状态为二进制
    stream.Position = position; // 恢复到改变前的位置
    stream.Write(binaryData);
    // 但是在发送前,还需要把流的位置设置为0,
    // 因为Microsoft.XMLHttp对象不会帮我们把ADODB.Stream的位置改为0,
    // 从0开始读取数据,而是从流的最后位置开始读。

    stream.Position = 0;// 位置设置为0
    httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
    httpRequest.open("POST", "test.jsp", true);
    httpRequest.setRequestHeader('Content-Type', 'multipart/form-data, boundary=' + boundary);
    httpRequest.setRequestHeader("Content-Length", stream.Size);
    httpRequest.send(stream); // 发送流

    4.
    完整的封装代码就不发出来了,没什么意义,用上文给出的三个帖子cut&copy就可以了。



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=572530

  • 相关阅读:
    CS round--36
    Vijos 1002 过河 dp + 思维
    汇编模拟36选7
    1137
    E. Mike and Foam 容斥原理
    Even-odd Boxes hackerrank 分类讨论
    112. 作业之地理篇 最小费用最大流模板题
    1550: Simple String 最大流解法
    Sam's Numbers 矩阵快速幂优化dp
    java.sql.SQLSyntaxErrorException: ORA-01722: 无效数字
  • 原文地址:https://www.cnblogs.com/ghx88/p/434080.html
Copyright © 2020-2023  润新知