NodeJS 如何将图片上传到本地S3存储桶并自动生成缩略图?

jchrr9hc  于 11个月前  发布在  Node.js
关注(0)|答案(3)|浏览(129)

晚上好
我有这个任务。我必须上传一个图像到S3桶使用 NodeJS 和生成一个缩略图在去,而不是通过使用一个lambda触发器。一切都应该做在我的本地机器终端(或)在本地服务器( Postman )。我尝试了这个代码。

const fs = require('fs');

const ACESS_ID = 'A**********KV';
const SECRET_ID = 'G***********0';
const BUCKET_NAME = 'node-image-bucket';

// Initializing s3 interface
const s3 = new AWS.S3({
    accessKeyId: ACESS_ID,
    secretAccessKey: SECRET_ID,
});

// File reading function to S3
const uploadFile = (fileName) => {
    // Read content from the file
    const fileContent = fs.readFileSync(fileName);

    // Setting up S3 upload parameters
    const params = {
        Bucket: BUCKET_NAME,
        Key: 'scene2.jpg',
        Body: fileContent
    };

    // Uploading files to the bucket
    s3.upload(params, function(err, data){
        if(err){
            throw err;
        }
        console.log(data);

        console.log(`File uploaded Successfully. ${data.Location}`);
    });
};

uploadFile('./images/bg-hd.jpg');

字符串

  • 以上代码在单个映像下运行良好,问题是每次将文件上传到S3存储桶时,我都需要更改S3参数的密钥字符串值 *
    我想一次上传多个图像,并创建一个缓冲区以提高性能,它应在不同文件夹的同一存储桶中自动创建缩略图。

有人能帮帮我吗,伙计们!求你了任何帮助,谢谢!

0yycz8jy

0yycz8jy1#

你不能用 one s3操作上传多个文件,但你可以在上传https://www.npmjs.com/package/sharp之前使用sharp模块调整图片大小,然后调用s3 API。

import * as sharp from 'sharp';

async function resize(buffer , width, height) {
  return sharp(buffer).resize(width, height).toBuffer();
}

const thumbnailWidthSize = 200;
const thumbnailWidthHeight = 200;
const thumbnailImage = await resize(fileContent, thumbnailWidthSize, thumbnailWidthHeight)

字符串
然后,您可以重用当前的upload函数,并使用不同的键多次运行它来调整图像大小,并将这些调用 Package 在promise.all周围,以便在任何上传失败时使操作失败。

await promise.all([ 
  s3upload(image, imageKey), 
  s3upload(thumbnailImage, thumbnailImageKey) 
])

snz8szmq

snz8szmq2#

所以,你的问题有两个部分-

*在上传到s3 bucket时将图像转换为动态缩略图-

您可以使用thumbd npm模块并创建一个thumbd服务器。

  • Thumbd是一个基于Node.js、SQS、S3和ImageMagick的图像缩略图服务器。*
    **thumbd服务器的先决条件-**Thumbd需要设置以下环境变量:
    *AWS_KEY您的AWS帐户的密钥(IAM用户必须有权访问相应的SQS和S3资源)。
    *AWS_SECRETAWS密钥。
    *BUCKET用于下载原图的存储桶,缩略图也会放在此存储桶中
    *AWS_REGION存储桶的AWS区域。地址:us-east-1。
    *CONVERT_COMMANDImageMagick转换命令。转换。
    *REQUEST_TIMEOUT在终止远程请求之前等待多长时间(以毫秒为单位)。请调整为15000。
    *S3_ACL上传镜像要设置的ACL,必须为private或public-read,默认为private。
    *S3_STORAGE_CLASS上传图片的存储类别,必须为STANDARD或REDUCED_REDUNDANCY. NORTH到STANDARD。
    *SQS_QUEUE监听镜像缩略图的队列名称。
  • 在本地运行时,我在.env文件中设置这些环境变量,并使用pm2/forever/foreman执行thumbd。
    设置-
  • apt-get install imagemagick
  • npm install thumbd -g
  • thumbd安装
  • thumbd start //将thumbd作为服务器运行

thumbd服务器启动并运行后,请参考以下代码,在上传到s3 bucket时将图像更改为缩略图。

var aws = require('aws-sdk');
    var url = require("url");
    var awsS3Config = { 
        accessKeyId: ACESS_ID,
        secretAccessKey: SECRET_ID,
        region: 'us-west-2' 
        }

    var BUCKET_NAME = 'node-image-bucket';
    var sourceImageDirectory = "/tmp/"
    var imageUploadDir = "/thumbnails/"
    var imageName = 'image.jpg'
    var uploadImageName = 'image.jpg'

    aws.config.update(awsS3Config);
    var s3 = new aws.S3();

    var Client = require('thumbd').Client,
        client = new Client({
            awsKey: awsS3Config.accessKeyId,
            awsSecret: awsS3Config.secretAccessKey,
            s3Bucket: BUCKET_NAME,
            sqsQueue: 'ThumbnailCreator',
            awsRegion: awsS3Config.region,
            s3Acl: 'public-read'
        });

    export function uploadAndResize(sourceImageDirectory, imageName, imageUploadDir, uploadImageName) {

       return new Promise((resolve, reject)=>{

            client.upload(sourceImageDirectory + imageName, imageUploadDir + uploadImageName, function(err) {

            if (err) {

                reject(err);
            } else {
                client.thumbnail(imageUploadDir + uploadImageName, [{
                    "suffix": "medium",
                    "width": 360,
                    "height": 360,
                    "background": "white",
                    "strategy": "%(command)s %(localPaths[0])s -resize %(width)sX%(height)s^ -gravity north -extent %(width)sX%(height)s  %(convertedPath)s"
                }, {
                    "suffix": "thumb",
                    "width": 100,
                    "height": 100,
                    "background": "white",
                    "strategy": "%(command)s %(localPaths[0])s -resize %(width)sX%(height)s^ -gravity north -extent %(width)sX%(height)s  %(convertedPath)s"
                }], {
                    //notify: 'https://callback.example.com'
                });
                var response = {};

                //https://s3-ap-us-west-2.amazonaws.com/node-image-bucket/1/5825c7d0-127f-4dac-b802-ca24efba2bcd-original.jpeg

                response.url = 'https://s3-' + awsS3Config.region + '.amazonaws.com/' + BUCKET_NAME + '/' + imageUploadDir;
                response.uploadImageName = uploadImageName;
                response.sourceImageName = imageName;

                 resolve(response);

                }

            })
       })

字符串
1.其次,你想上传多张图片而不改变字符串-
对本地路径中的所有文件循环下面的方法,你就可以开始了。

export function uploadFiles(localPath, localFileName, fileUploadDir, uploadFileName) {

  return new Promise((resolve, reject) => {

    fs.readFile(localPath + localFileName, function (err, file) {
      if (err) {

        reject(err);
      }

      var params = {
        ACL: 'public-read',
        Bucket: BUCKET_NAME,
        Key: uploadFileName,
        Body: file
      };

      s3.upload(params, function (err, data) {

        fs.unlink(localPath + localFileName, function (err) {

          if (err) {
            reject(err);
          } else {
            resolve(data)
          }
        });
      });

    });

  })

}

yhuiod9q

yhuiod9q3#

无需存储在本地文件系统中

import ffmpeg from "fluent-ffmpeg";
import { Readable } from "stream";
import ffprobeinstaller from '@ffprobe-installer/ffprobe';
import ffmpeginstaller from "@ffmpeg-installer/ffmpeg"
import { s3 } from "./S3Utils";

ffmpeg.setFfmpegPath(ffmpeginstaller.path)
ffmpeg.setFfprobePath(ffprobeinstaller.path)

export const generateThumbnail = async (file:Express.Multer.File,filename:string) => {
    
    try {
        const readableStream = Readable.from(file.buffer); 
        const thumbnailStream = ffmpeg()
          .input(readableStream)
          .inputFormat("mp4")
          .outputOptions("-ss", "00:00:02", "-vframes", "1")
          .outputFormat("image2")
          .on("end", () => console.log("Thumbnail generation finished"))
          .on("error", (err) => {
            console.error("Error during thumbnail generation:", err);
            throw Error("Failed to generate thumbnail" );
          })
          .pipe();
        
        const params = {
          Bucket: process.env.AWS_S3_BUCKET_NAME || "",
          Key: filename,
          Body: thumbnailStream,
          ContentType: "image/png", 
        };
        
        return s3.upload(params).promise();
    } catch (error) {
      console.error(error);
      throw new Error("Failed to generate thumbnail");
    }
};

字符串

相关问题