Ajax二进制响应

17

嗨,我想知道是否有一种方法可以在 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
  }
});
6个回答

23

可能无法直接进行二进制数据的流式传输,但您可以使用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);

Typed Arrays不支持IE < 10,Firefox < 4,Chrome < 7,Safari < 5.1和Opera < 11.6,而移动端支持不稳定但正在改善
第二种方法使用XMLHttpRequest方法称为overrideMimeType,以允许二进制数据通过未修改的方式传递。
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) & 0xff; 来获取特定的字节。

1
为什么使用 'text\/plain; charset=x-user-defined' 而不是 'text\/plain\;\ charset\=x\-user\-defined' 或者 'text/plain; charset=x-user-defined'? :) - mykhal

7

这是对汤姆·阿什沃斯的回应的一个扩展(帮助我解决了我遇到的问题)。这允许您只获取文件流(如果您正在使用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。请参见此处此处。请注意支持的浏览器。

5
如果您想动态生成一张图片,可以尝试使用以下代码:
<img src="http://myurl/myfile.php?id=3" />

接下来,您可以使用适当的MIME类型发送数据。

如果您确实想发送图像,则可能要查看HTML5画布标签,但我不确定excanvas如何与此配合使用,因为它是跨平台的。

您可以写入画布,但使用img标记会更有效率。


2
当您调用服务时,应请求 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
    }
});

祝你好运! :)


1

你可以发送任何响应,无论是纯文本、HTML、图像等等!当你接收到它时,你可以自己决定如何处理。

但是...你不能将二进制图像分配给<IMG>的src属性。最好只返回图像的URL并将其分配给该属性 - 说实话,有一些编码可以嵌入SRC中的图像,但它们不是跨浏览器的,所以最好远离它们。


1

我成功使用jQuery ajax下载二进制文件并避免数据损坏,方法是添加:

xhrFields: {responseType: 'blob'}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接