使用来自Ajax请求数据URI的原始图像数据

我正在尝试使用Ajax和数据URI的组合来加载JPEG图像,并使用一个HTTP请求来提取其EXIF数据。 我正在修改一个库( https://github.com/kennydude/photosphere )来做到这一点; 目前这个库使用两个HTTP请求来设置图像的来源并获取EXIF数据。

获得EXIF的作品,没有问题。 但是,我有困难使用来自ajax请求的原始数据作为图像的来源。

源代码的技术小testing:

<!DOCTYPE html> <html> <head> <script type='text/javascript'> function init() { // own ajax library - using it to request a test jpg image new Ajax().sendRequest ( "http://img.dovov.comphotos/badger.jpg", { method : "GET", callback: function(xmlHTTP) { var encoded = btoa (unescape(encodeURIComponent(xmlHTTP.responseText))); var dataURL="data:image/jpeg;base64,"+encoded; document.getElementById("image").src = dataURL; } } ); } </script> <script type="text/javascript" src="http://www.free-map.org.uk/0.6/js/lib/Ajax.js"></script> </head> <body onload='init()'> <img id="image" alt="data url loaded image" /> </body> </html> 

我得到的东西看起来像返回的明智的JPEG数据,原始数据的长度(以字节为单位)和base64编码,然后未编码的原始数据是相同的。 然而,在Firefox(25)和Chrome(31)(当前版本)上尝试设置图像src失败 – chrome显示“broken image”图标,提示src是无效的格式。

我使用这个Mozilla页面上的信息base64编码/解码:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding

任何想法可能是错的? 环顾四周我可以创buildbase64编码的图像服务器端,但可以做到这样的客户端? 首先,base64编码服务器端明显增加了数据大小,而这个练习的目的是为了减less从服务器传输的数据量以及请求数量。

谢谢,尼克

感谢那。 我已经做了一些更深入的研究,事实certificate至less在当前版本的Firefox和Chrome上有一个解决scheme(编辑:IE10也可以)。 您可以使用XMLHttpRequest2并使用一个types数组(Uint8Array)。 以下代码工作:

 <!DOCTYPE html> <html> <head> <script type='text/javascript'> function init() { var xmlHTTP = new XMLHttpRequest(); xmlHTTP.open('GET','http://img.dovov.comphotos/badger.jpg',true); // Must include this line - specifies the response type we want xmlHTTP.responseType = 'arraybuffer'; xmlHTTP.onload = function(e) { var arr = new Uint8Array(this.response); // Convert the int array to a binary string // We have to use apply() as we are converting an *array* // and String.fromCharCode() takes one or more single values, not // an array. var raw = String.fromCharCode.apply(null,arr); // This works!!! var b64=btoa(raw); var dataURL="data:image/jpeg;base64,"+b64; document.getElementById("image").src = dataURL; }; xmlHTTP.send(); } </script> </head> <body onload='init()'> <img id="image" alt="data url loaded image" /> </body> </html> 

基本上你要求一个二进制响应,然后在将数据转换回(二进制友好)stringString.fromCharCode()之前,创build一个8位无符号整型数据视图。 应用程序是必要的,因为String.fromCharCode()不接受数组参数。 然后,您使用btoa(),创build您的数据url,然后工作。

以下资源对此有用:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays?redirectlocale=en-US&redirectslug=JavaScript%2FTyped_arrays

http://www.html5rocks.com/en/tutorials/file/xhr2/

缺口

我遇到了上面描述的ArrayBuffer -> String -> Base64方法的问题,但是运行了另外一个使用Blob的方法,效果很好。 这不是一种将原始数据转换为Base 64(如标题中所示)的方法,但它显示原始图像数据的一种方式(如实际问题所示):

 var xhr = new XMLHttpRequest(); xhr.responseType = 'arraybuffer'; xhr.onload = function() { var blb = new Blob([xhr.response], {type: 'image/png'}); var url = (window.URL || window.webkitURL).createObjectURL(blb); image.src = url; } xhr.open('GET', 'http://whatever.com/wherever'); xhr.send(); 

所有功劳都归功于这位小提琴手的作者扬·米索夫斯基(Jan Miksovsky)。 我只是偶然发现了这个问题,并认为这会成为这次讨论的有益补充。

尼克的回答很好。 但是当我用一个相当大的文件做了这个,我得到了一个堆栈溢出

 var raw = String.fromCharCode.apply(null,arr); 

以块为单位生成原始string对我来说工作得很好。

 var raw = ''; var i,j,subArray,chunk = 5000; for (i=0,j=arr.length; i<j; i+=chunk) { subArray = arr.subarray(i,i+chunk); raw += String.fromCharCode.apply(null, subArray); } 

您将不得不在服务器端执行base64编码,因为responseText被视为string,并且服务器正在发送的响应数据是二进制的。