首页 文章

NodeJS:将base64编码的图像保存到磁盘

提问于
浏览
109

My Express应用程序从浏览器接收base64编码的PNG(使用toDataURL()从canvas生成)并将其写入文件 . 但该文件不是有效的图像文件,“文件”实用程序只是将其标识为“数据” .

var body = req.rawBody,
  base64Data = body.replace(/^data:image\/png;base64,/,""),
  binaryData = new Buffer(base64Data, 'base64').toString('binary');

require("fs").writeFile("out.png", binaryData, "binary", function(err) {
  console.log(err); // writes out file without error, but it's not a valid image
});

6 回答

  • 15

    从具有base64字符串的文件转换为png图像 .

    有效的4种变体 .

    var {promisify} = require('util');
    var fs = require("fs");
    
    var readFile = promisify(fs.readFile)
    var writeFile = promisify(fs.writeFile)
    
    async function run () {
    
      // variant 1
      var d = await readFile('./1.txt', 'utf8')
      await writeFile("./1.png", d, 'base64')
    
      // variant 2
      var d = await readFile('./2.txt', 'utf8')
      var dd = new Buffer(d, 'base64')
      await writeFile("./2.png", dd)
    
      // variant 3
      var d = await readFile('./3.txt')
      await writeFile("./3.png", d.toString('utf8'), 'base64')
    
      // variant 4
      var d = await readFile('./4.txt')
      var dd = new Buffer(d.toString('utf8'), 'base64')
      await writeFile("./4.png", dd)
    
    }
    
    run();
    
  • 3

    我认为您转换的数据比您需要的多一点 . 使用正确的编码创建缓冲区后,只需将缓冲区写入文件即可 .

    var base64Data = req.rawBody.replace(/^data:image\/png;base64,/, "");
    
    require("fs").writeFile("out.png", base64Data, 'base64', function(err) {
      console.log(err);
    });
    

    new Buffer(...,'base64')通过将输入解释为base64编码的字符串,将输入字符串转换为Buffer,这只是一个字节数组 . 然后你可以把那个字节数组写到文件中 .

    更新

    正如评论中所提到的, req.rawBody 不再是一件事 . 如果您正在使用 express / connect ,那么您应该使用 bodyParser() 中间件并使用 req.body ,如果您使用标准节点执行此操作,则需要聚合传入的 data 事件 Buffer 对象并在 end 回调中执行此图像数据解析 .

  • 1

    这是我的完整解决方案,它将读取任何base64图像格式并将其以适当的格式保存在数据库中:

    // Save base64 image to disk
        try
        {
            // Decoding base-64 image
            // Source: http://stackoverflow.com/questions/20267939/nodejs-write-base64-image-file
            function decodeBase64Image(dataString) 
            {
              var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
              var response = {};
    
              if (matches.length !== 3) 
              {
                return new Error('Invalid input string');
              }
    
              response.type = matches[1];
              response.data = new Buffer(matches[2], 'base64');
    
              return response;
            }
    
            // Regular expression for image type:
            // This regular image extracts the "jpeg" from "image/jpeg"
            var imageTypeRegularExpression      = /\/(.*?)$/;      
    
            // Generate random string
            var crypto                          = require('crypto');
            var seed                            = crypto.randomBytes(20);
            var uniqueSHA1String                = crypto
                                                   .createHash('sha1')
                                                    .update(seed)
                                                     .digest('hex');
    
            var base64Data = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAZABkAAD/4Q3zaHR0cDovL25zLmFkb2JlLmN...';
    
            var imageBuffer                      = decodeBase64Image(base64Data);
            var userUploadedFeedMessagesLocation = '../img/upload/feed/';
    
            var uniqueRandomImageName            = 'image-' + uniqueSHA1String;
            // This variable is actually an array which has 5 values,
            // The [1] value is the real image extension
            var imageTypeDetected                = imageBuffer
                                                    .type
                                                     .match(imageTypeRegularExpression);
    
            var userUploadedImagePath            = userUploadedFeedMessagesLocation + 
                                                   uniqueRandomImageName +
                                                   '.' + 
                                                   imageTypeDetected[1];
    
            // Save decoded binary image to disk
            try
            {
            require('fs').writeFile(userUploadedImagePath, imageBuffer.data,  
                                    function() 
                                    {
                                      console.log('DEBUG - feed:message: Saved to disk image attached by user:', userUploadedImagePath);
                                    });
            }
            catch(error)
            {
                console.log('ERROR:', error);
            }
    
        }
        catch(error)
        {
            console.log('ERROR:', error);
        }
    
  • 1

    更新

    我发现了这个interesting link how to solve your problem in PHP . 我想您忘了将 space 替换为 + ,如链接所示 .

    我把这个圈子从http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png作为样本看起来像:

    http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png

    接下来我把它通过了http://www.greywyvern.com/code/php/binary2base64,它让我回头:

    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAAAAACPAi4CAAAAB3RJTUUH1QEHDxEhOnxCRgAAAAlwSFlzAAAK8AAACvABQqw0mAAAAXBJREFUeNrtV0FywzAIxJ3+K/pZyctKXqamji0htEik9qEHc3JkWC2LRPCS6Zh9HIy/AP4FwKf75iHEr6eU6Mt1WzIOFjFL7IFkYBx3zWBVkkeXAUCXwl1tvz2qdBLfJrzK7ixNUmVdTIAB8PMtxHgAsFNNkoExRKA+HocriOQAiC+1kShhACwSRGAEwPP96zYIoE8Pmph9qEWWKcCWRAfA/mkfJ0F6dSoA8KW3CRhn3ZHcW2is9VOsAgoqHblncAsyaCgcbqpUZQnWoGTcp/AnuwCoOUjhIvCvN59UBeoPZ/AYyLm3cWVAjxhpqREVaP0974iVwH51d4AVNaSC8TRNNYDQEFdlzDW9ob10YlvGQm0mQ+elSpcCCBtDgQD7cDFojdx7NIeHJkqi96cOGNkfZOroZsHtlPYoR7TOp3Vmfa5+49uoSSRyjfvc0A1kLx4KC6sNSeDieD1AWhrJLe0y+uy7b9GjP83l+m68AJ72AwSRPN5g7uwUAAAAAElFTkSuQmCC
    

    将此字符串保存到我在代码中读取的 base64 .

    var fs      = require('fs'),
    data        = fs.readFileSync('base64', 'utf8'),
    base64Data,
    binaryData;
    
    base64Data  =   data.replace(/^data:image\/png;base64,/, "");
    base64Data  +=  base64Data.replace('+', ' ');
    binaryData  =   new Buffer(base64Data, 'base64').toString('binary');
    
    fs.writeFile("out.png", binaryData, "binary", function (err) {
        console.log(err); // writes out file without error, but it's not a valid image
    });
    

    我得到了一个圆圈,但有趣的是文件大小已经改变:)...

    结束

    当您回读图像时,我认为您需要设置 Headers

    以PHP页面为例imagepng

    <?php
    $im = imagecreatefrompng("test.png");
    
    header('Content-Type: image/png');
    
    imagepng($im);
    imagedestroy($im);
    ?>
    

    我认为第二行 header('Content-Type: image/png'); ,重要的是你的图像不会在浏览器中显示,但只有一堆二进制数据显示给浏览器 .

    Express中,您只需使用下面的内容即可 . 我要显示你的gravatar,它位于http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG,当你 curl --head http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG 时是一个jpeg文件 . 我只请求 Headers ,因为其他curl会显示一堆二进制内容(谷歌Chrome立即下载)到控制台:

    curl --head "http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG"
    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 03 Aug 2011 12:11:25 GMT
    Content-Type: image/jpeg
    Connection: keep-alive
    Last-Modified: Mon, 04 Oct 2010 11:54:22 GMT
    Content-Disposition: inline; filename="cabf735ce7b8b4471ef46ea54f71832d.jpeg"
    Access-Control-Allow-Origin: *
    Content-Length: 1258
    X-Varnish: 2356636561 2352219240
    Via: 1.1 varnish
    Expires: Wed, 03 Aug 2011 12:16:25 GMT
    Cache-Control: max-age=300
    Source-Age: 1482
    

    $ mkdir -p ~/tmp/6922728
    $ cd ~/tmp/6922728/
    $ touch app.js
    

    app.js

    var app = require('express').createServer();
    
    app.get('/', function (req, res) {
        res.contentType('image/jpeg');
        res.sendfile('cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG');
    });
    
    app.get('/binary', function (req, res) {
        res.sendfile('cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG');
    });
    
    app.listen(3000);
    
    $ wget "http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG"
    $ node app.js
    
  • 236

    base64 图像转换为文件并将其另存为随机ID或名称的简便方法 .

    // to create some random id or name for your image name
    const imgname = new Date().getTime().toString();
    
    // to declare some path to store your converted image
    const path = yourpath.png    
    
    // image takes from body which you uploaded
    const imgdata = req.body.image;    
    
    // to convert base64 format into random filename
    const base64Data = imgdata.replace(/^data:([A-Za-z-+/]+);base64,/, '');
    fs.writeFile(path, base64Data, 'base64', (err) => {
        console.log(err);
    });
    
    // assigning converted image into your database
    req.body.coverImage = imgname
    
  • 18

    我还必须保存作为数据URL一部分的Base64编码图像,所以我最终制作了一个小的npm模块,以防万一我(或其他人)将来再次需要这样做 . 它被称为ba64 .

    简而言之,它采用带有Base64编码图像的数据URL并将图像保存到文件系统中 . 它可以同步或异步保存 . 它还有两个辅助函数,一个用于获取图像的文件扩展名,另一个用于将Base64编码与 data: 方案前缀分开 .

    这是一个例子:

    var ba64 = require("ba64"),
        data_url = "data:image/jpeg;base64,[Base64 encoded image goes here]";
    
    // Save the image synchronously.
    ba64.writeImageSync("myimage", data_url); // Saves myimage.jpeg.
    
    // Or save the image asynchronously.
    ba64.writeImage("myimage", data_url, function(err){
        if (err) throw err;
    
        console.log("Image saved successfully");
    
        // do stuff
    });
    

    安装它: npm i ba64 -S . Repo在GitHub上:https://github.com/HarryStevens/ba64 .

    附:后来我发现ba64可能是该模块的一个坏名称,因为人们可能会认为它做Base64编码和解码,但它没有(有很多模块已经这样做了) . 那好吧 .

相关问题