【问题标题】:How to be able to convert image to base64 and avoid same-origin Policy如何能够将图像转换为 base64 并避免同源策略
【发布时间】:2015-06-21 01:47:05
【问题描述】:

我正在尝试将图像(链接)转换为 base64 以便能够存储在浏览器端(IndexedDB)中,但我无法做到这一点,我已经寻找解决方案好几天了,我没有解决我的问题。

在这个很棒的代码中,我能够将图像从 Internet 转换为 Base64,但问题是由于同源策略,我无法对 Internet 上的其他图像执行此操作。

我将如何避免该问题,或者如果您知道将图像转换为 Base64 的任何其他解决方案,那将非常有帮助

function convertImgToBase64URL(url, callback, outputFormat){
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas = document.createElement('CANVAS'),
        ctx = canvas.getContext('2d'), dataURL;
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        callback(dataURL);
        canvas = null; 
    };
    img.src = url;
}
convertImgToBase64URL('http://upload.wikimedia.org/wikipedia/commons/4/4a/Logo_2013_Google.png', function(base64Img){
alert('it works');
      $('.output').find('img').attr('src', base64Img);  
   
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="output"> <img> </div>

【问题讨论】:

  • 此代码似乎将图像转换为 base64 没有任何错误。您面临的确切错误/问题是什么?
  • 您应该尝试从网络上获取另一张图片以了解错误,无论如何感谢您的评论
  • 我尝试使用来自谷歌搜索的随机图片 url 以及来自本地服务器的图片,并且没有错误,这就是为什么问。
  • 试试这张图片http://www.pariskop.fr/wp-content/uploads/2014/12/psg-revons-plus-grand1.jpg
  • 我得到了错误。我认为如果没有服务器的某种支持,就无法直接或通过XMLHttpRequest 访问图像。可能是this 帮助您了解原因

标签: javascript html image base64


【解决方案1】:

在转换为 base64 时,您可以在图像路径前使用代理 URL (https://cors-anywhere.herokuapp.com/) 以避免跨域问题

var getDataUri = function (targetUrl, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        var reader = new FileReader();
        reader.onloadend = function () {
            callback(reader.result);
        };
        reader.readAsDataURL(xhr.response);
    };
    var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    xhr.open('GET', proxyUrl + targetUrl);
    xhr.responseType = 'blob';
    xhr.send();
};
getDataUri(path, function (base64) {
    // base64 availlable here
})

【讨论】:

  • 由于某种原因,此请求在 Firefox 88.0 中失败
【解决方案2】:

您需要先将图像下载到字节数组中: Downloading binary data using XMLHttpRequest, without overrideMimeType

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.celticfc.net/images/doc/celticcrest.png', true);

xhr.responseType = 'arraybuffer';

xhr.onload = function(e) {
   if (this.status == 200) {
       var uInt8Array = new Uint8Array(this.response); // Note:not xhr.responseText

       for (var i = 0, len = uInt8Array.length; i < len; ++i) {
           uInt8Array[i] = this.response[i];
       }

       var byte3 = uInt8Array[4]; // byte at offset 4
   }
}

xhr.send();

那么就可以使用字节数组如下:Javascript : How to display image from byte array using Javascript or Servlet?

<img id="ItemPreview" src="" />

document.getElementById("ItemPreview").src = "data:image/png;base64," + YourByteArray;

编辑:我无法尝试此 ATM,但您也可以使用 HTML5 FileSystem API 将文件保存到文件系统:How to save a image to HTML5 filesystem with the url of image

window.requestFileSystem(window.PERSISTENT, 2*1024*1024, onFileSystemSuccess, fail);


function onFileSystemSuccess(fileSystem) {
    fs = fileSystem;
    console.log('File system initialized');

    saveAsset('http://www.example-site-with-cors.com/test.png');
}


function saveAsset(url, callback, failCallback) {
    var filename = url.substring(url.lastIndexOf('/')+1);

    // Set callback when not defined
    if (!callback) {
        callback = function(cached_url) {
            console.log('download ok: ' + cached_url);
        };
    }
    if (!failCallback) {
        failCallback = function() {
            console.log('download failed');
        };
    }

    // Set lookupTable if not defined
    if (!window.lookupTable)
        window.lookupTable = {};

    // BlobBuilder shim
    // var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    // xhr.responseType = 'blob';
    xhr.responseType = 'arraybuffer';

    xhr.addEventListener('load', function() {

        fs.root.getFile(filename, {create: true, exclusive: false}, function(fileEntry) {
            fileEntry.createWriter(function(writer) {

                writer.onwrite = function(e) {
                    // Save this file in the path to URL lookup table.
                    lookupTable[filename] = fileEntry.toURL();
                    callback(fileEntry.toURL());
                };

                writer.onerror = failCallback;

                // var bb = new BlobBuilder();
                var blob = new Blob([xhr.response], {type: ''});
                // bb.append(xhr.response);
                writer.write(blob);
                // writer.write(bb.getBlob());

            }, failCallback);
        }, failCallback);
    });

    xhr.addEventListener('error', failCallback);
    xhr.send();

    return filename;
}



function fail(evt) {
    console.log(evt.target.error.code);
}

【讨论】:

  • 这是一个非常聪明的解决方案,请您提供 Jsfiddle 演示,因为我正在尝试测试,但无法使其工作,再次感谢 :)
  • 小提琴在哪里?
  • XMLHttpRequest 无法接收来自其服务器执行同源策略的网站的响应(即,不要为 XMLHttpRequest 客户端的来源设置Access-Control-Allow-Origin),所以这没有用。此外,HTML5 FileSystem API 是非标准的,因此仅适用于some browsers
【解决方案3】:

对于同源策略,您必须从您想要图像的位置添加服务器端的标头

这里是如何做到这一点 - http://enable-cors.org/server.html

出于开发目的,您可以在 CHROME 浏览器中安装“CORS”扩展程序以允许跨源请求

希望这有助于解决您的问题。

【讨论】:

  • 这里的问题是他无法控制服务器
  • 安装 CORS 是客户端浏览器扩展,因此这将允许跨域请求...
  • 只有开发阶段,生产呢?
猜你喜欢
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 2011-09-11
  • 2015-12-09
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多