使用 multer 将多个图像上传到 AWS S3
Posted
技术标签:
【中文标题】使用 multer 将多个图像上传到 AWS S3【英文标题】:Uploading multiple images with multer to AWS S3 【发布时间】:2021-04-04 11:44:07 【问题描述】:我目前有一个后端,我可以使用 multer 上传多个图像。这些图像通过sharp调整图像大小以创建完整的缩略图图像。帖子的条目存储在我数据库的帖子表中,图像的文件名也存储在我数据库的 Post_Images 表中。
我的问题是我目前正在使用 multer diskStorage 将我的图像存储在我的磁盘上,现在我想将图像存储在 AWS S3 上。
我试图实现这一点,但没有成功。
posts.js
const s3 = new AWS.S3(
accessKeyId: process.env.AWS_ID,
secretAccessKey: process.env.AWS_SECRET
Bucket:process.env.AWS_BUCKET
)
const storage = multer.diskStorage(
destination: function (req, file, callback)
callback(null, "./uploads");
,
filename: function (req, file, callback)
console.log(file.originalname);
callback(null, file.originalname + "-" + new Date().toISOString() + "-" + uuidv4());
,
);
const multerS3Config = multerS3(
s3: s3,
bucket: process.env.AWS_BUCKET,
metadata: function (req, file, cb)
cb(null, fieldName: file.fieldname );
,
key: function (req, file, cb)
console.log(file)
// cb(null, file.originalname + "-" + new Date().toISOString() + "-" + uuidv4())//
cb(null, new Date().toISOString() + "-" + uuidv4()+ "-" + file.originalname)
);
const upload = multer(
storage: multerS3Config,
limits: fieldSize: 25 * 1024 * 1024 ,
);
router.post(
"/",
[
upload.array("images", config.get("maxImageCount")),
imageResize,
],
async (req, res) =>
const paths = await req.files.map((file) => ( fileName: file.filename ));
await Post.create(
title: req.body.title,
userId: req.body.userId,
Post_Images: paths.map((x) => ( images: x.fileName
)),
,
include: [Post_Image] ).then(
res.status(201).send()
ImageResize.js
const sharp = require("sharp");
const path = require("path");
const fs = require("fs");
const outputFolder = "public/assets";
module.exports = async (req, res, next) =>
const images = [];
const resizePromises = req.files.map(async (file) =>
await sharp(file.path)
.resize(2000)
.jpeg( quality: 50 )
.toFile(path.resolve(outputFolder, file.filename + "_full.jpg"));
await sharp(file.path)
.resize(100)
.jpeg( quality: 30 )
.toFile(path.resolve(outputFolder, file.filename + "_thumb.jpg"));
fs.unlinkSync(file.path);
images.push(file.filename);
);
await Promise.all([...resizePromises]);
req.images = images;
next();
;
每次我尝试上传帖子时,我都会收到
UnhandledPromiseRejectionWarning: Error: Invalid input
我认为我收到此错误是因为我不再使用我的磁盘存储,因此我无权访问 file.path 和 file.filename。
当我在 ImageREsize.js 中间件中执行 console.log(file) 时,我得到了这个
fieldname: 'images', originalname: 'FILENAME', encoding: '7bit',
mimetype: 'image/jpeg', size: 38184, bucket: 'BUCKET NAME', key:
'IMAGE NAME', acl: 'private', contentType: 'application/octet-
stream', contentDisposition: null, storageClass: 'STANDARD',
serverSideEncryption: null, metadata: fieldName: 'images' ,
location: 'IMAGE LINK', etag: '""', versionId: undefined
更新
最初我试图使用 multerS3 来完成此操作,但在查看了几个答案后,我决定尝试一下。要使用普通 multer 处理传入文件,请使用Sharp调整其大小并使用AWS-SDK将每个调整大小的文件上传到S3。
图像的条目正在存储在我的 postgres 数据库中,但随后我得到了一个
Error: Input file is missing
当我检查我的桶时它是空的。
这是我的代码
posts.js
const s3 = new AWS.S3(
accessKeyId: process.env.AWS_ID,
secretAccessKey: process.env.AWS_SECRET,
Bucket:process.env.AWS_BUCKET,
region:process.env.AWS_REGION
)
const storage=multer.memoryStorage()
const upload = multer(
storage: storage,
limits: fieldSize: 25 * 1024 * 1024 ,
);
router.post(
"/",
[ upload.array("images", config.get("maxImageCount")),
imageResize,
],
async (req, res) =>
const paths = await req.files.map((file) => ( originalName:
file.originalname + "-" + new Date().toISOString() + "-" + uuidv4()
));
await Post.create(
title: req.body.title,
userId: req.body.userId,
Post_Images: paths.map((x) => ( images: x.originalName
)),
,
include: [Post_Image] ).then(
res.status(201).send()
imageResize.js
const sharp = require("sharp");
const path = require("path");
const fs = require("fs");
const outputFolder = "public/assets";
require("dotenv").config();
const AWS = require('aws-sdk')
const s3 = new AWS.S3(
accessKeyId: process.env.AWS_ID,
secretAccessKey: process.env.AWS_SECRET,
Bucket:process.env.AWS_BUCKET,
region:process.env.AWS_REGION
)
module.exports = async (req, res, next) =>
const images = [];
const resizePromises = req.files.map(async (file) =>
console.log(file)
await sharp(file)
.resize(2000)
.jpeg( quality: 50 )
.toBuffer()
.then(resized=>s3.upload(
Bucket:process.env.AWS_BUCKET,
key:file.originalname + "-" + new Date().toISOString() + "-" + uuidv4() + "_full.jpg",
Body:resized
));
await sharp(file)
.resize(100)
.jpeg( quality: 30 )
.toBuffer()
.then(resized=>s3.upload(
Bucket:process.env.AWS_BUCKET,
key:file.originalname + "-" + new Date().toISOString() + "-" + uuidv4() + "_thumb.jpg",
Body:resized
));
fs.unlinkSync(file.buffer);
images.push(file.originalname);
);
await Promise.all([...resizePromises]);
req.images = images;
next();
;
【问题讨论】:
评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:我设法让它工作,我的问题是我的 imageResize 中间件。我必须将 AWS S3 存储到我拥有的代码中,而不是将其保存到磁盘。
posts.js
const storage=multer.memoryStorage()
const upload = multer(
storage: storage,
limits: fieldSize: 25 * 1024 * 1024 ,
);
router.post(
"/",
[ upload.array("images", config.get("maxImageCount")),
imageResize,
],
async (req, res) =>
const paths = await req.files.map((file) => ( originalName: file.originalname));
await Post.create(
title: req.body.title,
userId: req.body.userId,
Post_Images: paths.map((x) => ( images: x.originalName )),
,
include: [Post_Image] ).then(
res.status(201).send())
imageResize.js
const sharp = require("sharp");
require("dotenv").config();
const AWS = require('aws-sdk')
const s3 = new AWS.S3(
accessKeyId: process.env.AWS_ID,
secretAccessKey: process.env.AWS_SECRET,
region:process.env.AWS_REGION
)
module.exports = async (req, res, next) =>
const images = [];
const resizePromises = req.files.map(async (file) =>
console.log(file)
await sharp(file.buffer)
.resize(2000)
.jpeg( quality: 50 )
.toBuffer()
.then(resized=>s3.upload(
Bucket:process.env.AWS_BUCKET,
Key:file.originalname + "_full.jpg",
Body:file.buffer,
ACL: 'public-read'
).promise()),
await sharp(file.buffer)
.resize(100)
.jpeg( quality: 30 )
.toBuffer()
.then(resized=>s3.upload(
Bucket:process.env.AWS_BUCKET,
Key:file.originalname + "_thumb.jpg",
Body:file.buffer,
ACL: 'public-read'
).promise())
images.push(file.originalname);
);
await Promise.all([...resizePromises]);
req.images = images;
next();
;
【讨论】:
以上是关于使用 multer 将多个图像上传到 AWS S3的主要内容,如果未能解决你的问题,请参考以下文章
使用 Multer 和 Express 将多个图像上传到 Cloudinary