使用JavaScript将图像URL转换为数据URL

22

使用JavaScript,我想将类似于以下的img标签转换:

<img width="11" height="14" src="http://mysite/file.gif" alt="File Icon">

转换成一个类似于这样的dataurl:

<img width="11" height="14" src="data:image/gif;base64,R0lGODlhCwAOAMQfAP////7+/vj4+Hh4eHd3d/v7+/Dw8HV1dfLy8ubm5vX19e3t7fr6+nl5edra2nZ2dnx8fMHBwYODg/b29np6eujo6JGRkeHh4eTk5LCwsN3d3dfX13Jycp2dnevr6////yH5BAEAAB8ALAAAAAALAA4AAAVq4NFw1DNAX/o9imAsBtKpxKRd1+YEWUoIiUoiEWEAApIDMLGoRCyWiKThenkwDgeGMiggDLEXQkDoThCKNLpQDgjeAsY7MHgECgx8YR8oHwNHfwADBACGh4EDA4iGAYAEBAcQIg0Dk gcEIQA7" alt="File Icon">

这可行吗?


你为什么想要这样做? - Brad
1
因为 jsPDF 似乎只支持那样的图片。 - adam0101
4
我不认为这与那个回答重复,因为他是从服务器下载二进制数据并将其转换为Base64。我试图在客户端将绝对URL转换为Base64,如果可能的话,避免再次下载。 - adam0101
@adam0101 但是你必须先下载它一次以转换数据。然后,使用base64图像可以防止重新下载图像及其字符串。这样做可以有效地减少图像下载的时间和带宽消耗。 - Romain Braun
1
@RomainBraun,那个问题和答案将字符串转换为Base64。我没有要转换的字符串,只有一个URL。btoa()函数不接受URL。 - adam0101
4个回答

37

以下是使用fetch获取图像数据URL的方法:

(async function() {
    let blob = await fetch("https://example.com/image.png").then(r => r.blob());
    let dataUrl = await new Promise(resolve => {
      let reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.readAsDataURL(blob);
    });
    // now do something with `dataUrl`
})();

这返回的是 data:text/html,我正在尝试获取 data:image/png - S. Stark
然后在你的字符串中将text/html替换为image/png。 - jdmayfield

20

首先,将图像加载到画布中

var canvas = document.createElement("canvas");
context = canvas.getContext('2d');

make_base();

function make_base()
{
  base_image = new Image();
  base_image.src = 'img/base.png';
  base_image.onload = function(){
    context.drawImage(base_image, 100, 100);
  }
}

请确保更新context.drawImage(base_image, 100, 100);中的值适合您的应用程序。

来源:https://dev59.com/tG025IYBdhLWcg3wbVan#6011402

然后将画布转换为数据。

var jpegUrl = canvas.toDataURL("image/jpeg");
var pngUrl = canvas.toDataURL(); // PNG is the default

来源: https://dev59.com/fWUo5IYBdhLWcg3w5Syl#15685877


1
谢谢!这个方法很好用,但是我发现如果我在jsPDF中包含html2canvas,它会自动为我转换图片! - adam0101

5
我会尝试用一个与加载的图像大小相同的临时画布元素来解决这个问题:
function imageToUri(url, callback) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    var base_image = new Image();
    base_image.src = url;
    base_image.onload = function() {
        canvas.width = base_image.width;
        canvas.height = base_image.height;

        ctx.drawImage(base_image, 0, 0);
    
        callback(canvas.toDataURL('image/png'));

        canvas.remove();
    }
}

imageToUri('./assets/some_image.png', function(uri) {
    console.log(uri);
});

1
这并不是JavaScript中建议做的事情,因为它需要在JavaScript中解析图像,这非常慢。你将加载图像,然后将函数输出放入img标签中,这不会节省带宽、减少复杂性或提高安全性。
你最好在服务器端完成此操作。我过去曾经使用过这个方法,以生成绝对没有链接/引用外部资源的页面。对于jsPDF,你可以使用原始JavaScript或jQuery获取图像数据,以传递到PDF创建过程中。
这将在任何地方都起作用,并且不依赖于只有部分移动浏览器支持的canvas

如果我将数据存储在本地存储中会怎样呢?首先,我会下载图像,然后将其存储在用户的本地存储中。然后用户可以从他们的本地存储中加载该图像。如果图像已经被下载,那么用户可以跳过下载部分,这可能会提高性能。这样做可以吗? - DxTx
1
浏览器缓存处理得相当不错,因此在大多数应用程序中,您不需要在大多数项目中将图像存储在本地存储中。如果这是您真正想要做的事情,那么有另一个SO问题涵盖了这个问题。它使用画布,但现代所有Web浏览器都支持它:
  • https://dev59.com/DGIk5IYBdhLWcg3wiuqk
- Liam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接