如何将画布数据保存到文件

Posted

技术标签:

【中文标题】如何将画布数据保存到文件【英文标题】:how to save canvas data to file 【发布时间】:2011-08-17 13:47:11 【问题描述】:

我正在使用 node.js 将画布保存到图像 writeFile 中的 img 是通过在我的画布元素上使用 toDataURL 提取的。 它不保存文件 这是我的代码

var fs = IMPORTS.require('fs');
var path = IMPORTS.require('path');
path.exists('images/', function(exists)
    if (exists) 

        fs.writeFile('images/icon.png', img, function(err)
            if (err) 
                callback(
                    error: false,
                    reply: err
                );
            console.log('Resized and saved in');
            callback(
                error: false,
                reply: 'success.'
            );
        );
    
    else 
        callback(
            error: true,
            reply: 'File did not exist.'
        );
    
 );    

【问题讨论】:

您能否包含您的画布代码或您正在测试的 url,以便我们无需编写任何样板即可运行您的代码? (请参阅sscce.org)如果您希望人们提供帮助,您可能还需要详细说明您的描述。 【参考方案1】:

这是一个如何在 Nodejs 中将画布数据保存到文件的文字示例。变量imgcanvas.toDataURL() 生成的字符串。我假设您已经知道如何将该字符串从浏览器发布到您的 Nodejs 服务器。

生成我使用的示例图像的 html sn-p:

<canvas id="foo"  ></canvas>
<script>
var ctx = $('#foo')[0].getContext('2d');
for (var x = 0; x < 20; x += 10) 
    for (var y = 0; y < 20; y += 10) 
        if (x == y)  ctx.fillStyle = '#000000'; 
        else  ctx.fillStyle = '#8888aa'; 
        ctx.fillRect(x, y, 10, 10);
    

console.log($('#foo')[0].toDataURL());
</script>

Nodejs sn -p 解码base64数据并保存图片:

const fs = require("fs").promises;

(async () => 
  
  // string generated by canvas.toDataURL()
  const img = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0"
      + "NAAAAKElEQVQ4jWNgYGD4Twzu6FhFFGYYNXDUwGFpIAk2E4dHDRw1cDgaCAASFOffhEIO"
      + "3gAAAABJRU5ErkJggg==";
  
  // strip off the data: url prefix to get just the base64-encoded bytes
  const data = img.replace(/^data:image\/\w+;base64,/, "");
  
  const buf = Buffer.from(data, "base64");
  await fs.writeFile("image.png", buf);
)();

输出:

【讨论】:

谢谢!我不知道我需要Buffer,我只是想将base64.decode() 与base64 数据一起使用,但生成了一个损坏的文件。 服务器代码示例对我有用。有人可以解释一下为什么它不适用于这些数据:pastebin.com/raw.php?i=3yhGiQWR 我的缓冲区未定义 对我来说,toDataUrl() 字符串包括加号,body-parserrequest.body 中变成了空格,所以我不得不再次用加号替换它们,这样我的 png 就不会损坏: var data=img.slice(img.indexOf(',')+1).replace(/\s/g,'+'); new Buffer 已被弃用 per nodejs。在这种情况下,您现在应该使用Buffer.from(data, 'base64');【参考方案2】:

我相信Canvas 不会在内部将其数据存储在 Base64 中。它应该以更有效的二进制格式存储数据。因此,很明显,转换到 base64 再转换回二进制 PNG 非常缓慢且消耗内存。

快速搜索到node canvas documentation 给出:

要创建一个PNGStream,只需调用canvas.pngStream(),该流将开始发射数据事件,最后在完成时发射结束。如果发生异常,则会发出错误事件。

var fs = require('fs')
  , out = fs.createWriteStream(__dirname + '/text.png')
  , stream = canvas.pngStream();

stream.on('data', function(chunk)
  out.write(chunk);
);

stream.on('end', function()
  console.log('saved png');
);

目前仅支持同步流式传输。如果您想异步执行,可以尝试使用工作线程或集群(我个人从未尝试过)。

【讨论】:

这个答案更好/更干净/更强。 console.log('saved png') 发生在文件保存之前。这是因为只支持同步吗? 文件保存后如何触发事件?

以上是关于如何将画布数据保存到文件的主要内容,如果未能解决你的问题,请参考以下文章

将 HTML5 画布图像保存到数据库

如何将使用 InkCanvas 在画布上完成的工作保存到 UWP C# 中的图像文件?

保存画布图像(将数据字符串发布到 PHP)

将画布作为 jpg 文件保存到服务器时如何增加 DPI?

如何在不使用画布的情况下将整个 div 数据转换为图像并将其保存到目录中?

将 three.js 生成的画布保存到服务器 - 没有文件被保存