如何使用Node.js将缓冲区转换为图像?

5
这是我从S3存储桶获取图像的代码,但结果是缓冲区,我需要将其转换成图像。请告诉我怎么做。
const AWS = require('aws-sdk')
const fs = require('fs')
const express = require('express')
const app = express()
app.get('/', (req, res) => {
  const s3 = new AWS.S3({
    accessKeyId: '################',
    secretAccessKey: '###############################',
    region: '###########'
  })

  const params = {
    Bucket: '#########',
    Key: '########'
  }
  s3.getObject(params, (err, rest) => {
    res.send(rest)
  })
})

app.listen(3000)

输出

{
  AcceptRanges: 'bytes',
  LastModified: 2020-06-29T10:42:17.000Z,
  ContentLength: 338844,
  ETag: '"769af0d798cd0486993711bc63340bd0"',
  ContentType: 'application/octet-stream',
  Metadata: {},
  Body: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff db 00 84 00 02 02 02 
  02 02 02 02 02 02 02 03 03 02 03 03 04 03 03 03 03 04 06 04 04 04 ... 338794 
  more bytes>
}

这完全取决于你想如何显示这张图片。如果你想在HTML中显示它,答案会与将其保存为文件有所不同。 - Matt Oestreich
我需要在使用端口的情况下在浏览器中显示图像。 - Sethu
3个回答

8

简而言之:

/**
 * FINAL/WORKING SOLUTION
 */

// ...
app.get('/', (req, res) => {
  const s3 = new AWS.S3({
    accessKeyId: '-',
    secretAccessKey: '-',
    region: '-',
  });

  const params = {
    Bucket: '-',
    Key: '-',
  };

  s3.getObject(params, (err, rest) => {
    if (err) throw err;

    const b64 = Buffer.from(rest.Body).toString('base64');
    // CHANGE THIS IF THE IMAGE YOU ARE WORKING WITH IS .jpg OR WHATEVER
    const mimeType = 'image/png'; // e.g., image/png
    
    res.send(`<img src="data:${mimeType};base64,${b64}" />`);
  });
});
// ...

您需要使用node来“渲染”图像,也就是只需将响应作为<img />标签发送即可。
// ...
app.get('/', (req, res) => {
  const s3 = new AWS.S3({
    accessKeyId: '-',
    secretAccessKey: '-',
    region: '-',
  });

  const params = {
    Bucket: '-',
    Key: '-',
  };

  s3.getObject(params, (err, rest) => {
    if (err) throw err;

    const b64 = Buffer.from(rest).toString('base64');
    // NOTE: 
    // Because 'rest' appears to be a buffer, you might not 
    // need to do `Buffer.from(...)`,you may have to do something like:
    /** const b64 = rest.toString('base64'); **/
    const mimeType = 'image/png'; // e.g., image/png
    
    res.send(`<img src="data:${mimeType};base64,${b64}" />`);
  });
});
// ...

编辑1:

我认为问题与从S3返回给您的数据有关。您可能需要执行类似于rest.Bodyrest.body之类的操作-我不确定S3对象的外观。

话虽如此,我将这张图片本地保存为sample.png,并使用以下代码进行加载-它可以正常工作。这证明了问题与S3返回数据的方式有关。

const fs = require('fs');
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  // Simulate getting data from S3 (aka data as buffer)
  const rest = Buffer.from(fs.readFileSync('./sample.png'));

  console.log('typeof rest = ' + typeof rest + '\r\n\r\n', rest);
  // typeof rest = object
  //
  // <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 01 34 00 00 00 a4 08 03 00 00 00 2e 4e 22 5a 00 00 00 a2 50 4c 54 45 f7 f7 f7 cd 00 00 d1 00 00 ... 6360 more bytes>


  const b64 = rest.toString('base64');
  const mimeType = 'image/png'; // e.g., image/png

  res.send(`<img src="data:${mimeType};base64,${b64}" />`);
});

app.listen(3000);

编辑 2:

看起来你需要这样做:

// ...
app.get('/', (req, res) => {
  const s3 = new AWS.S3({
    accessKeyId: '-',
    secretAccessKey: '-',
    region: '-',
  });

  const params = {
    Bucket: '-',
    Key: '-',
  };

  s3.getObject(params, (err, rest) => {
    if (err) throw err;

    const b64 = Buffer.from(rest.Body).toString('base64');
    // IF THE ABOVE LINE DOES NOT WORK, TRY THIS:
    // const b64 = rest.Body.toString('base64');

    // CHANGE THIS IF THE IMAGE YOU ARE WORKING WITH IS .jpg OR WHATEVER
    const mimeType = 'image/png'; // e.g., image/png
    
    res.send(`<img src="data:${mimeType};base64,${b64}" />`);
  });
});
// ...

它显示了一些错误:TypeError [ERR_INVALID_ARG_TYPE]:第一个参数必须是字符串类型或者Buffer、ArrayBuffer、Array或类似于数组的对象的实例。收到了Object的一个实例。 - Sethu
我已经做了一些更改,它可以工作,但不如我预期的那样,它只在浏览器中显示图像图标而不是整个图像。 - Sethu
@Sethu请查看我的回答底部 - 我已经添加了一些更新。 - Matt Oestreich
1
感谢您的帮助,@Matt Oestreich。 - Sethu
我理解Lambda / Azure Functions / Google所提供的服务背后的逻辑..这才是重要的。它基本上只是处理路由。此外,手头的问题与Lambda无关=/ - Matt Oestreich
显示剩余8条评论

0

1. 尝试使用 Jimp 库将图像转换为缓冲区,这样可以将其保存在数据库中。

 const imagePath = `path/to/image`;
  const jimpImageToBuffer = await jimp
    .read(imagePath) // read image from path
    .then((ele) => {
      const mimeForImage = ele._originalMime;
      return ele.getBufferAsync(mimeForImage); // convert image to buffer(compatiable to save to database).
    })
    .catch((err) => console.log(err));
  console.log(jimpImageToBuffer); // <- image in buffer format

请查看下面的链接,了解有关将图像转换为缓冲区的jimp实现和完整说明。

https://dev59.com/SKfja4cB1Zd3GeqPuVvr#72798711


0
首先,将缓冲区转换为字符串(在本例中,我们使用base64字符串)。 然后,返回一个简单的HTML页面来显示base64字符串图像。
以下是将缓冲区转换为字符串的函数。
  const encode = (data) => {
    let buf = Buffer.from(data);
    let base64 = buf.toString('base64');
    return base64
  }

将HTML页面发送给客户端:
    const html = `<html><body><img src='data:image/jpeg;base64,${encode(rest.Body)}'/></body></body></html>`
    res.send(html)

如你所见,rest.Body是图像的缓冲内容。
最终代码:
const AWS = require('aws-sdk')
const fs = require('fs')
const express = require('express')
const app = express()
app.get('/', (req, res) => {
  const s3 = new AWS.S3({
    accessKeyId: '################',
    secretAccessKey: '###############################',
    region: '###########'
  })

  const params = {
    Bucket: '#########',
    Key: '########'
  }

  const encode = (data) => {
    let buf = Buffer.from(data);
    let base64 = buf.toString('base64');
    return base64
  }

  s3.getObject(params, (err, rest) => {
    const html = `<html><body><img src='data:image/jpeg;base64,${encode(rest.Body)}'/></body></body></html>`
    res.send(html)
  })
})

app.listen(3000)

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