23

我想做的事:

使用 jQuery.ajax() 从基本身份验证安全服务器 HTTP-GET 图像 (jpeg)。好像我得到了图像的一些数据,它必须是二进制的。我想将其转换为base64,因为这样我可以将其作为图像插入到我的html中:

     $("#image").attr('src', 'data:image/jpeg;base64,' + base64encode(data));

ajax 调用如下所示:

            $.ajax({
                url: "someurltoajpeg",
                type: "GET",
                headers: {
                    "Authorization" : "Basic " +  btoa("user:pw")
                },
                xhrFields: {
                    withCredentials: true
                }
            }).done(function( data, textStatus, jqXHR ) {
                $("#image").attr('src', 'data:image/jpeg;base64,' + base64encode(data));
            }).fail(function( jqXHR, textStatus, errorThrown ) {
                alert("fail: " + errorThrown);
            });

函数 base64encode 如下所示:

        function base64encode(binary) {
            return btoa(unescape(encodeURIComponent(binary)));
        }

我从这里得到了这个功能: Retrieving binary file content using Javascript, base64 encode it and reverse-decode it using Python

他在那里说这对他有用。但在我的情况下,我的图像的 src 属性发生了变化,并且插入了一些很长的数据,但只出现了应该存在的图像的非常小的符号。我可以保存那个“图像”,那甚至不在那里,当我打开它时,我的图像查看器说它不是 jpeg 文件。这不是特定图像或同源策略引起的错误。有没有人解决这个问题?谢谢

4

2 回答 2

33

首先,根据Retrieving binary file content using Javascript, base64 encode it and reverse-decode it using Python添加正确的 mimetype 到 Ajax 调用:

 $.ajax({
            url: "someurltoajpeg",
            type: "GET",
            headers: {
                "Authorization" : "Basic " +  btoa("user:pw")
            },
            xhrFields: {
                withCredentials: true
            },
            mimeType: "text/plain; charset=x-user-defined"
        }).done(function( data, textStatus, jqXHR ) {
            $("#image").attr('src', 'data:image/jpeg;base64,' + base64encode(data));
        }).fail(function( jqXHR, textStatus, errorThrown ) {
            alert("fail: " + errorThrown);
        });

然后使用描述的base64Encode函数而不是btoa:

function base64Encode(str) {
        var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var out = "", i = 0, len = str.length, c1, c2, c3;
        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                out += CHARS.charAt(c1 >> 2);
                out += CHARS.charAt((c1 & 0x3) << 4);
                out += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                out += CHARS.charAt(c1 >> 2);
                out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
                out += CHARS.charAt((c2 & 0xF) << 2);
                out += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            out += CHARS.charAt(c1 >> 2);
            out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
            out += CHARS.charAt(c3 & 0x3F);
        }
        return out;
    }

再见

于 2014-08-18T20:03:28.943 回答
1

如果您不必支持 IE 9,则可以使用FileReaderAPI将 blob 转换为数据 URL。它提供了一个readAsDataURL()接受 Blob 作为第一个参数的方法。读取 blob 后,它会触发一个load事件并在result属性上提供数据 URL。

这更稳定并且需要更少的代码,因为它不需要自定义编码为 base64 字符串,这是一项考虑到限制的复杂任务btoa

您可以使用jQuery.ajax()fetch将文件加载为Blob

jQuery.ajax(url, {
  dataType: 'binary',
  xhr() {
    let myXhr = jQuery.ajaxSettings.xhr();
    myXhr.responseType = 'blob';
    return myXhr;
  }
}).then((response) => {
  // response is a Blob
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.addEventListener('load', () => {
      // reader.result holds a data URL representation of response
      resolve(reader.result);
    }, false);
    reader.addEventListener('error', () => {
      reject(reader.error);
    }, false);
    reader.readAsDataURL(response);
  });
});

此示例代码使用Promise,但如果使用回调,它的工作方式类似。

于 2018-09-24T20:06:14.407 回答