Javascript 使用来自ajax的原始图像数据请求数据URI
我尝试使用Ajax和数据URI的组合来加载JPEG图像,并通过一个HTTP请求提取其EXIF数据。我正在修改一个库()来实现这一点;目前,该库使用两个HTTP请求来设置映像的源和获取EXIF数据 让EXIF工作,没问题。但是,我很难使用来自ajax请求的原始数据作为图像的源 技术小型测试的源代码:Javascript 使用来自ajax的原始图像数据请求数据URI,javascript,ajax,image,base64,Javascript,Ajax,Image,Base64,我尝试使用Ajax和数据URI的组合来加载JPEG图像,并通过一个HTTP请求提取其EXIF数据。我正在修改一个库()来实现这一点;目前,该库使用两个HTTP请求来设置映像的源和获取EXIF数据 让EXIF工作,没问题。但是,我很难使用来自ajax请求的原始数据作为图像的源 技术小型测试的源代码: <!DOCTYPE html> <html> <head> <script type='text/javascript'> function init
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>
function init()
{
// own ajax library - using it to request a test jpg image
new Ajax().sendRequest
(
"/images/photos/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>
函数init()
{
//拥有ajax库-使用它请求测试jpg图像
新建Ajax().sendRequest
(
“/images/photos/badger.jpg”,
{方法:“获取”,
回调:函数(xmlHTTP)
{
var encoded=btoa(unescape(encodeURIComponent(xmlHTTP.responseText));
var dataURL=“数据:图像/jpeg;base64,”+编码;
document.getElementById(“image”).src=dataURL;
}
}
);
}
我使用此mozilla页面获取有关base64编码/解码的信息:
你知道哪里不对吗?环顾四周,我可以创建base64编码的图像服务器端,但它可以像这样在客户端完成吗?首先,base64编码服务器端明显增加了数据大小,而此练习的全部目的是减少从服务器传输的数据量以及请求数
谢谢,
Nick您必须在服务器端进行base64编码,因为responseText被视为字符串,服务器发送的响应数据是二进制的 谢谢你。我对此做了更多的挖掘,结果发现至少在当前版本的Firefox和Chrome上有一个解决方案(编辑:IE10也可以)。您可以使用XMLHttpRequest2和类型化数组(Uint8Array)。以下代码起作用:
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>
function init()
{
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.open('GET','/images/photos/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>
函数init()
{
var xmlHTTP=new XMLHttpRequest();
open('GET','/images/photos/badger.jpg',true);
//必须包含此行-指定所需的响应类型
xmlHTTP.responseType='arraybuffer';
xmlHTTP.onload=函数(e)
{
var arr=新的Uint8Array(this.response);
//将int数组转换为二进制字符串
//转换*数组时必须使用apply()*
//fromCharCode()接受一个或多个单个值,而不是
//数组。
var raw=String.fromCharCode.apply(null,arr);
//这很有效!!!
var b64=btoa(原始);
var dataURL=“数据:图像/jpeg;base64,”+b64;
document.getElementById(“image”).src=dataURL;
};
xmlHTTP.send();
}
基本上,您需要一个二进制响应,然后创建数据的8位无符号int视图,然后再将其转换回(二进制友好的)字符串。fromCharCode()。应用是必需的,因为String.fromCharCode()不接受数组参数。然后使用btoa(),创建数据url,然后它就可以工作了
以下资源对此很有用:
及
尼克的回答很有效。但是,当我用一个相当大的文件执行此操作时,我得到了一个堆栈溢出
var raw = String.fromCharCode.apply(null,arr);
在块中生成原始字符串对我来说很好
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);
}
var raw='';
变量i,j,子数组,区块=5000;
对于(i=0,j=arr.length;i我在上面描述的ArrayBuffer->String->Base64
方法中遇到了问题,但遇到了另一种使用该方法的方法,效果非常好。这不是将原始数据转换为Base 64的方法(如标题所示),而是显示原始图像数据的一种方法(如实际问题所示):
所有的功劳都归功于Jan Miksovsky,他的作者。我只是偶然发现了它,并认为它会对本次讨论作出有益的补充。我已经为此问题工作了两天,因为我需要一个解决方案来根据从Microsoft Graft收到的原始数据呈现用户的Outlook配置文件图片。我已经实现了上述所有解决方案,但没有成功。然后我找到了这个git:
在我的例子中,我只是将“data:image/png;base64”
替换为“data:image/jpg;base64”
它就像一个魔咒。现代ES6图像下载解决方案:(不指定图像类型)
我做了更多的挖掘,结果发现有一个解决方案,至少在现代HTML5浏览器中(适用于当前的Firefox/Chrome)。此外,为了支持IE9,您必须在此项目中包含typedarray.js。这定义了Uint8Array。这是使其在iOS和Android上工作所必需的技巧。感谢您发布这篇文章!很棒的帖子。我现在终于可以发表评论了,但如果您因为文件太大而遇到堆栈溢出错误,请参阅下面的答案!做得好!我已经完成了要做一些测试,但现在,这对我来说很有吸引力!除此之外,如果您右键单击在另一个选项卡中打开文件,与ArrayBuffer->String->Base64方法相比,您没有这么长的URL。(顺便说一句:“webkitURL”已被弃用。请改用“URL”)
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();
async function downloadImageFromUrl(url) { // returns dataURL
const xmlHTTP = new XMLHttpRequest();
xmlHTTP.open('GET', url, true);
xmlHTTP.responseType = 'blob';
const imageBlob = await new Promise((resolve, reject) => {
xmlHTTP.onload = e => xmlHTTP.status >= 200 && xmlHTTP.status < 300 && xmlHTTP.response.type.startsWith('image/') ? resolve(xmlHTTP.response) : reject(Error(`wrong status or type: ${xmlHTTP.status}/${xmlHTTP.response.type}`));
xmlHTTP.onerror = reject;
xmlHTTP.send();
});
return blobToDataUrl(imageBlob);
}
function blobToDataUrl(blob) { return new Promise(resolve => {
const reader = new FileReader(); // https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
reader.onload = e => resolve(e.target.result);
reader.readAsDataURL(blob);
})}
downloadImageFromUrl('https://a.b/img.png').then(console.log, console.error)