如何在Javascript中将图像二进制从API调用转换为数据URI?

时间:2011-12-06 02:41:11

标签: javascript google-api data-uri

我正在使用的Google API仅将图像作为二进制数据传输。

我绝对不知道如何将其放入数据URI中以显示它,感谢您的帮助!

我正在谈论的电话是this API call

如你所见,它说:

  

服务器返回照片的字节。

对于调用(它是扩展名),我使用chrome_ex_oauth方法。也许我需要在标题中添加一些内容来获取真正的二进制数据,而不是现在出现的字符串......

我需要做的是将生成的二进制文件转换为数据URI,以便我可以显示它。


好的,我从XHR请求中得到了这个

enter image description here

现在,我不太了解二进制的东西。这是以某种方式编码的二进制数据我假设?我试图把它放到btoa和其他base64编码器中,一切都会引发错误。 我尝试使用不同的东西覆盖MySQL类型,并以某些奇怪的方式更改“响应”,但没有接受数据。

现在我有了这段代码:

var nxhr = new XMLHttpRequest();
nxhr.onreadystatechange = function (data) {
    if (nxhr.readyState == 4) {
        console.log(nxhr);
    }
};
nxhr.open(method, url, true);
nxhr.setRequestHeader('GData-Version', '3.0');
nxhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
nxhr.send('Data to send');

其他任何人都知道如何为我获取这个不可理解的响应数据uri ???

感谢您的帮助

5 个答案:

答案 0 :(得分:16)

在进行一些测试之后,这是我的答案:

要使用<img>标记只显示图像,必须先使用Base64对结果二进制文件进行编码。您可以通过两种不同的方式完成此任务:

  1. 使用Javascript:使用Base64编码器功能such as this one。对结果二进制数据进行编码后,您可以使用<img>标记显示图像,如下所示:<img src="data:image/*;base64,[BASE64 ENCODED BINARY]" />。您必须将[BASE64 ENCODED BINARY]替换为图像的实际编码二进制文件。我假设您已经知道如何通过Javascript更改HTML元素属性,将编码的二进制文件放入src标记的<img>属性中相当容易。

  2. 使用PHP(我的个人偏好):向API提交GET请求后,它会返回二进制文件。只需使用PHP base64_encode()函数。

    <img src="data:image/*;base64,<?php echo base64_encode($result); ?>" />

  3. 其中,$result变量是您从API调用中获得的变量。您可以使用PHP cURL库。

    我希望这会有所帮助。

答案 1 :(得分:5)

好的,我找到了解决方案......

首先,请求必须将returend Type覆盖为x-user-defined

xhr.overrideMimeType('text\/plain; charset=x-user-defined');

之后,浏览器不会触及数据。

使用以下Base64编码器

Base64 = {

            // private property
            _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

            encodeBinary: function (input) {
                var output = "";
                var bytebuffer;
                var encodedCharIndexes = new Array(4);
                var inx = 0;
                var paddingBytes = 0;

                while (inx < input.length) {
                    // Fill byte buffer array
                    bytebuffer = new Array(3);
                    for (jnx = 0; jnx < bytebuffer.length; jnx++)
                        if (inx < input.length)
                            bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; // throw away high-order byte, as documented at: https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data
                        else
                            bytebuffer[jnx] = 0;

                    // Get each encoded character, 6 bits at a time
                    // index 1: first 6 bits
                    encodedCharIndexes[0] = bytebuffer[0] >> 2;
                    // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)
                    encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4);
                    // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)
                    encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6);
                    // index 3: forth 6 bits (6 least significant bits from input byte 3)
                    encodedCharIndexes[3] = bytebuffer[2] & 0x3f;

                    // Determine whether padding happened, and adjust accordingly
                    paddingBytes = inx - (input.length - 1);
                    switch (paddingBytes) {
                        case 2:
                            // Set last 2 characters to padding char
                            encodedCharIndexes[3] = 64;
                            encodedCharIndexes[2] = 64;
                            break;
                        case 1:
                            // Set last character to padding char
                            encodedCharIndexes[3] = 64;
                            break;
                        default:
                            break; // No padding - proceed
                    }
                    // Now we will grab each appropriate character out of our keystring
                    // based on our index array and append it to the output string
                    for (jnx = 0; jnx < encodedCharIndexes.length; jnx++)
                        output += this._keyStr.charAt(encodedCharIndexes[jnx]);
                }
                return output;
            }
        };

mozilla发布的神奇内容并没有让我正确编码这些东西

bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff

最终的代码看起来就像这样...

oauth.authorize(function () {
    var method = "GET", params = {}, url = photo.href;

    var nxhr = new XMLHttpRequest();
    nxhr.onreadystatechange = function (data) {
        if (nxhr.readyState == 4) {
            console.log("<img src='data:image/*;base64," + Base64.encodeBinary(nxhr.response) + "' />");
        }
    };
    nxhr.open(method, url, true);
    nxhr.setRequestHeader('GData-Version', '3.0');
    nxhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
    nxhr.overrideMimeType('text\/plain; charset=x-user-defined'); 
});

P.S。如果直接将“data:image / *”放入浏览器窗口,它将下载该文件,但无法打开它。但是如果你把它直接放到img src中它就可以了!

答案 2 :(得分:2)

如果您使用的是data: URI,我认为您不关心旧浏览器。在这种情况下,请按照btoa()中的建议使用How can you encode a string to Base64 in JavaScript?,然后再回到the alternative mentioned in the second answer。然后,data: URI很简单:

data:image/*;base64,<the btoa output>

答案 3 :(得分:1)

所有其他解决方案都已过时。不需要Base64。查看my answer on Getting BLOB data from XHR request

答案 4 :(得分:1)

我知道这是一个非常古老的问题,但由于这是关于 XHR 上的图像和二进制数据,所以我的秘诀在于两个重要步骤:

步骤 1: 确保您使用自定义的用户定义字符集以防止浏览器更改内容。例如

xhr.overrideMimeType('text\/plain; charset=x-user-defined');

步骤 2: 使用 String.fromCharCode(response.charCodeAt(...) & 0xff) 解决 btoa() 无法处理二进制字符串的问题。这是受到@https://gist.github.com/graylikeme/867848 要点的启发(目前对我来说是黑魔法)。

最终结果:这是结果的简化版本。请注意,通常您也会这样做,因为您还需要发送 Authorization 标头或其他内容,但这并未包含在本示例中。

<div id="output-el"></div>
<script>
    var xhr = new XMLHttpRequest();
    xhr.addEventListener('readystatechange', function() {
        var outputEl = document.getElementById('xhr-output');

        // Done?
        if (this.readyState === 4) {

            // Make sure this is an image.
            var contentType = this.getResponseHeader('content-type');
            if (contentType !== null && contentType.indexOf('image/') === 0) {
                // Prepare binary response so we can base64 encode it (and btoa() function doesn't freak out).
                // Thanks to: https://gist.github.com/graylikeme/867848
                var response = this.responseText;
                var binary = '';
                for(i=0; i < response.length; i++) {
                    binary += String.fromCharCode(response.charCodeAt(i) & 0xff);
                }

                // Drop into data URI.
                var encoded = btoa(binary);
                outputEl.innerHTML = `<img alt="image preview" src="data:${contentType};base64,${encoded}">`;

            } else {
                console.log('Got a non-image response:', this.responseText);
            }
        }
    });

    // Make sure browser doesn't alter the response before we handle it.
    xhr.overrideMimeType('text\/plain; charset=x-user-defined');
    xhr.open('GET', 'https://example.com/path/to/some/image.jpg');
    xhr.send();
</script>