使用xmlhttprequest获取跨域PNG文件

时间:2012-11-06 22:38:51

标签: javascript image xmlhttprequest cross-domain cors

可悲的是,我看到了许多类似的问题,但没有任何答案似乎与我的情况有关。我不是在使用jquery。除了最新的浏览器(特别是Chrome),我不关心任何事情。我正在寻找一种从PNG或JPG文件的跨域提取加载javascript图像的方法。

即。我只是想这样做:

<pre>
var img1 = new Image();
img1.addEventListener('load', function() { imageLoaded( canvas, context, this); }, false)
img1.src = textureUrl;
</pre>

适用于同一个域名。但是,显然不会在请求标头中包含Origin标记,因此即使我们已成功在服务器上设置CORS标头,它也无法在跨域环境中工作。如果我可以对此请求做一些简单的事情来包含该标题,那就太棒了。

但我收集的是我要做的是使用XHR对资产进行异步获取,获取二进制数据,然后以某种方式将数据推送到常规的Image()对象中。我相信我们已经成功地以各种形式获得了数据(尝试过arraybuffer和blobs),但是没有成功地将它干扰到Image()对象中。

例如:

<pre>
var img3 = new Image();
var req = new window.XMLHttpRequest();
req.overrideMimeType('text/plain; charset=x-user-defined');  // seems to make no difference
req.responseType = 'arraybuffer';  // no joy with arraybuffer or blob
req.open("GET", textureUrl, true, "", "");  // async request allows CORS preflight exchange

req.onreadystatechange = function (oEvent) {
  if (req.readyState === 4) {
    if (req.status === 200) {
        alert( "XHR worked" );
        if( req.response ) {
          alert( "resp text: " + req.response );  // identifies response as arraybuffer or blob
        }

        // I believe this section is where I need the most help.

// var base64Img = window.btoa(unescape(encodeURIComponent(req.responseText)));

        var base64Img = window.btoa( unescape( encodeURIComponent( req.response ) ) );
        alert( "b64: " +  base64Img );  // vaguely uu64ish, but truncated
        var src = "";
        if( isPng == 1 ) {  // just to indicate the src url is built differently for jpg.
            alert("png");
            src = 'data:image/png;base64,' + base64Img;
        } 

        ....
        img3.src = src;  // img3 loads fine if I just jam a same domain url here

  <closing braces>

</pre>

根据我的阅读,我不清楚我是否需​​要覆盖mime类型,如果我指定了arraybuffer,但我不清楚。

我得到数据(没有跨域错误,是的),它似乎是正确的大小,但我不相信我成功uu64编码它,也不是我正在干扰一个合适的数据网址图像。

同样,我只需要使用最新的Chrome浏览器,我希望尽可能使用“纯HTML5”,所以我觉得不需要使用IE7等。

我不知道req.response是否包含HTTP响应的第一行(即我是否有责任在对其进行修改之前修剪它...)

希望你能从我眼中拉出羊毛!

提前致谢。

2 个答案:

答案 0 :(得分:0)

我有一段时间对同样的问题感到震惊。这是您需要做的工作:

对于zip / png等格式,您应该使用:

req.reponseType = 'arraybuffer';

棘手的是,在arraybuffer的情况下,req.responseText不起作用,而是使用req.response

var base64Img = window.btoa( unescape( encodeURIComponent( req.response ) ) );

答案 1 :(得分:0)

如果您对使用最新的HTML功能感到满意,则以下内容可能会有所帮助。

使用Fetch API加载二进制文件:

const response = await fetch('https://cross-origin.org/path-to-binary.png' , {
  cache: 'no-cache',
  mode: 'cors',
  credentials: 'omit'
});

if (!response.ok) {
  console.error(response);
  throw new Error(response.statusText);
}

console.log('response from fetch', response);
const blob = await response.blob();

要将Blob转换为base64,可以使用FileReader API

// Lang: Typescript
  private async convertBlobToBase64(blob: Blob): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onerror = reject;
      reader.onload = () => {
        resolve(reader.result as string);
      };
      reader.readAsDataURL(blob);
    });
  }