How can I convert image binary from API call to data URI in Javascript?

拟墨画扇 提交于 2019-11-29 04:21:58

After conducting some tests, here is my answer:

To simply display the image using the <img> tag, you must first encode the result binary with Base64. You can do this in two different ways:

  1. Using Javascript: Use a Base64 encoder function, such as this one. After you encode the result binary data, you can display the image using the <img> tag like so: <img src="data:image/*;base64,[BASE64 ENCODED BINARY]" />. You must replace [BASE64 ENCODED BINARY] with the actual encoded binary of the image. I'm assuming you already know how to change HTML element attributes through Javascript, it's fairly easy to put the encoded binary into the src attribute of the <img> tag.

  2. Using PHP (my personal preference): Once you submit a GET request to the API, it will return you the binary. Simply use the PHP base64_encode() function.

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

Where, the $result variable is what you get from the API call. You can use the PHP cURL library.

I hope this helps.

Luke

Ok I found the solution...

First of all, the request must override the returend Type into x-user-defined

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

After that the data is untouched by the browser.

Use the following Base64 encoder

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;
            }
        };

There is the magic stuff posted by mozilla which didnt let me encode the stuff correctly

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

The final code would look then like this...

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. If you put the "data:image/*" into the browser window directly, it will download the file and would not be able to open it. But if you put it directly into an img src it works fine!

Ry-

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>
Janus Troelsen

All the other solutions are obsolete. No Base64 is needed. Check out my answer on Getting BLOB data from XHR request.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!