【问题标题】:Ajax Binary ResponseAjax 二进制响应
【发布时间】:2010-12-11 09:03:48
【问题描述】:

您好,我想知道是否可以在 AJAX 中流式传输二进制响应?这将是一个终极解决方案,否则我需要将二进制图像实现为文件,然后将该文件流式传输给具有不同 URL 的用户。

new Ajax.Request('/viewImage?id=123', {
  // request returns a binary image inputstream
  onSuccess: function(transport) {
      // text example
      // alert(transport.responseText)

      // QUESTION: is there a streaming binary response?
      $('imgElem').src = transport.responseBinary;
  },
  onFailure: function(transport) {
      // handle failure
  }
});

【问题讨论】:

    标签: javascript ajax prototypejs


    【解决方案1】:

    您可以发送任何您想要的响应,可以是纯文本、HTML、图像……随便!收到后如何处理,由您自己决定。

    但是...您不能将二进制图像分配给<IMG> src 属性。您最好只返回图像的 URL 并分配它 - 好吧,老实说,有一些编码可以将图像嵌入 SRC,但它们不是跨浏览器,因此您需要远离它们.

    【讨论】:

      【解决方案2】:

      如果您试图动态生成图像,您可以做的就是:

      <img src="http://myurl/myfile.php?id=3" />
      

      然后您可以使用适当的 mimetype 发送数据。

      如果您真的想发送图像,那么您可能想查看 HTML5 canvas 标签,但我不确定 excanvas 将如何使用它,因为它是跨平台的。

      你可以写到画布上,但只使用 img 标签会更有效。

      【讨论】:

        【解决方案3】:

        可能无法流式传输二进制数据,但您可以使用 Ajax 检索二进制数据。

        这可以使用以下两种方法之一:Javascript Typed Arrays 或 XMLHttpResponse overrideMimeType hack。阅读 MDN 上的一篇好文章——这些示例取自那里:Sending and Receiving Binary Data

        Typed Array 方法如下所示:

        var oReq = new XMLHttpRequest();
        oReq.open("GET", "/myfile.png", true);
        oReq.responseType = "arraybuffer";
        
        oReq.onload = function (oEvent) {
          var arrayBuffer = oReq.response; // Note: not oReq.responseText
          if (arrayBuffer) {
            var byteArray = new Uint8Array(arrayBuffer);
            for (var i = 0; i < byteArray.byteLength; i++) {
              // do something with each byte in the array
            }
          }
        };
        
        oReq.send(null);
        

        IE mobile support is shaky but improving 不支持类型化数组。

        第二种方法使用一个名为 overrideMimeType 的 XMLHttpRequest 方法来允许二进制数据不加修改地通过。

        var req = new XMLHttpRequest();
        req.open('GET', '/myfile.png', false);
        // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
        req.overrideMimeType('text\/plain; charset=x-user-defined');
        req.send(null);
        if (req.status != 200) return '';
        // do stuff with req.responseText;
        

        您会得到一个未解析的二进制字符串,您可以在该字符串上使用var byte = filestream.charCodeAt(x) &amp; 0xff; 来检索特定字节。

        【讨论】:

        • 为什么是'text\/plain; charset=x-user-defined' 而不是例如'text\/plain\;\ charset\=x\-user\-defined''text/plain; charset=x-user-defined' ? :)
        【解决方案4】:

        这是对 Tom Ashworth 的回应的延伸(这有助于让我走上正轨,解决我所面临的问题)。这允许您只获取文件流(如果您使用的是 asp.net mvc,则为 FileStreamResult)并将其设置为 img src,这很酷。

        var oReq = new XMLHttpRequest();
        oReq.open("post", '/somelocation/getmypic', true );        
        oReq.responseType = "blob";
        oReq.onload = function ( oEvent )
        {
            var blob = oReq.response;
            var imgSrc = URL.createObjectURL( blob );                        
            var $img = $( '<img/>', {                
                "alt": "test image",
                "src": imgSrc
            } ).appendTo( $( '#bb_theImageContainer' ) );
            window.URL.revokeObjectURL( imgSrc );
        };
        oReq.send( null );
        

        基本思想是数据未经篡改地返回,它被放置在一个blob中,然后在内存中为该对象创建一个url。请参阅 herehere。注意支持的浏览器。

        【讨论】:

          【解决方案5】:

          当您致电您的服务时,您应该要求dataType: 'binary' 回复。然后,您可以使用saveAs(FileSaver.js) 触发下载或createObjectURL 在新窗口中打开。

          但是,$.ajax 不允许您开箱即用地下载二进制内容,它会尝试从 UTF-8 解码您的二进制文件并破坏它。要么使用jQuery插件来解决这个问题jquery.binarytransport.js

          示例:

          $.ajax({
              type: "POST",
              url: $("form#data").attr("action"),
              data: formData,
              dataType: 'binary',     //--> using jquery.binarytransport.js
              success: function (response) {
                  // Default response type is blob
                  
                  saveAs(response, "test.pdf"); //--> using FileSaver.js
          
                  let fileURL = URL.createObjectURL(blob);
                  window.open(fileURL);        // open file in new window
              }
          });
          

          好看! :)

          【讨论】:

            猜你喜欢
            • 2020-08-16
            • 2012-06-16
            • 2020-07-31
            • 2020-04-21
            • 2020-04-11
            • 1970-01-01
            • 1970-01-01
            • 2011-09-08
            • 2015-08-05
            相关资源
            最近更新 更多