【问题标题】:Javascript binary string concatenation on form-data in XMLHttpRequestXMLHttpRequest中表单数据的Javascript二进制字符串连接
【发布时间】:2015-03-09 23:22:51
【问题描述】:

我正在编写一个 Chrome 扩展程序,并且需要构建一个自定义表单数据来将一个 Zip 文件(我不能使用真正的 HTML 表单)上传到服务器(不是我的)。 我在这里找到了一种方法- https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Sending_forms_through_JavaScript(最后一节 - 处理二进制数据)。

它适用于明文文件,但我想发送二进制的 Zip。

似乎JavaScript无法处理二进制和非二进制的连接,并在我的文件中添加了一些0Xc2字符)-:

我还在http://footle.org/2007/07/31/binary-multipart-posts-in-javascript/找到了解决方案, 但它使用Components.classes["@mozilla.org/io/string-input-stream;1"],在Chrome扩展程序中不可用。

如何将二进制 zip 文件与字符串连接起来并将其上传到服务器?

function sendData(zipBinary) {

    var XHR      = new XMLHttpRequest();
    var boundary = "----WebKitFormBoundary3n9vu9ZOkCPW4HAw";
    var prefix     = "";
    var postfix     = "";

    prefix += "--" + boundary + "\r\n";
    prefix += 'content-disposition: form-data; '
          + 'name="'         + 'UploadedFile'          + '"; '
          + 'filename="'     + 'hello.zip' + '"\r\n';
    prefix += 'Content-Type: ' + 'application/x-zip-compressed' + '\r\n';
    prefix += '\r\n';
    postfix += '\r\n';

    // Once we are done, we "close" the body's request
    postfix += "--" + boundary + "--";
    postfix += '\r\n';

    XHR.addEventListener('load', function(event) {
      alert('Yeah! Data sent and response loaded.');
    });

    XHR.addEventListener('error', function(event) {
      alert('Oups! Something goes wrong.');
    });

    XHR.open('POST', 'https://example.com');
    XHR.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary);
    XHR.send(prefix + zipBinary + postfix); // <----
  }

【问题讨论】:

    标签: javascript google-chrome-extension xmlhttprequest binaryfiles multipartform-data


    【解决方案1】:

    您是否阅读了您链接的文章中的section about FormData?因为这是通过 XMLHttpRequest API 发送文件的最佳解决方案。与字符串连接相比,此 API 的优势在于文件可以以流式方式上传,而不必在发送前完全缓冲在内存中。

    假设zipBinaryBlobFile对象,你可以上传文件如下:

    function sendData(zipBinary) {
        var xhr = new XMLHttpRequest();
        var fd = new Formdata();
        fd.append('hello.zip', zipBinary);
        xhr.onload = function() {
             // Request completed! Use xhr.status and/or xhr.responseText to
             // check the server's response status code and response body.
        };
        xhr.onerror = function() {
             // Aw. Network error.
        };
        xhr.open('POST', 'https://example.com/');
        xhr.send(fd);
    }
    

    如果zipBinary 不是BlobFile 对象,而是一串二进制数据,那么您可以将其转换为具有指定MIME-type 的Blob,如下所示:

    function sendData(zipBinary) {
        var zipBinaryBytes = new Uint8Array(zipBinary.length);
        for (var i = 0; i < zipBinary.length; ++i) {
            zipBinaryBytes[i] = zipBinary.charCodeAt(i);
        }
        zipBinary = new Blob([zipBinaryBytes], { type: 'application/zip' });
        // rest of code as I suggested above...
    

    (注意:application/zip 是 zip 文件的官方 MIME 类型,而不是 application/x-zip-compressed


    如果你是 HTTP 协议的专家并且真的想完全手工编写 HTTP 请求正文,那么你需要发送一个类型化的数组而不是一个字符串,因为 XMLHttpRequest API @ 987654324@ 在将数据传递给服务器之前。这可以使用TextEncoder API 自 Chrome 38+ 来完成,应用到您的代码如下:

    // Was: XHR.send(prefix + zipBinary + postfix);
    // New
    XHR.send(new TextEncoder().encode(prefix + zipBinary + postfix));
    

    注意:您很少需要手动构建请求正文。除非您知道自己在做什么,否则必须手动构建请求正文通常表明您做错了

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 2013-03-25
      相关资源
      最近更新 更多