9

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

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

我正在谈论的调用是这个 API 调用

如您所见,它说:

服务器返回照片的字节数。

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

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


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

在此处输入图像描述

现在,我不太了解二进制的东西。这是我假设的某种编码二进制数据?我试图将它放入 btoa 和其他 base64 编码器中,一切都会引发错误。我试图用不同的东西覆盖MimeType,并且“响应”以一些奇怪的方式发生了变化,但没有任何东西接受数据。

所以现在我有这个代码:

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的响应???

谢谢你的帮助

4

5 回答 5

17

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

要使用标签简单地显示图像<img>,您必须首先使用 Base64 对结果二进制文件进行编码。您可以通过两种不同的方式执行此操作:

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

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

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

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

我希望这有帮助。

于 2011-12-18T22:30:45.773 回答
5

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

首先,请求必须覆盖return 类型为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'); 
});

PS如果直接把“data:image/*”放到浏览器窗口,会下载文件,打不开。但是,如果您将其直接放入 img src 中,它就可以正常工作!

于 2011-12-20T17:20:15.137 回答
2

所有其他解决方案都已过时。不需要 Base64。查看我关于从 XHR 请求获取 BLOB 数据的答案

于 2013-03-31T13:36:35.840 回答
1

If you're using a data: URI, I take it you don't care about older browsers. In that case, use btoa() as suggested in How can you encode a string to Base64 in JavaScript?, and fall back on the alternative mentioned in the second answer. Then, the data: URI is simple:

data:image/*;base64,<the btoa output>
于 2011-12-18T23:22:21.520 回答
1

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

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

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

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

End Eesult:这是结果的简化版本。请注意,通常您也会这样做,因为您还需要发送 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>
于 2021-03-26T20:35:17.557 回答