使用 Multer 将多个文件上传到 aws-s3(内部包含其他对象数组的对象)

问题描述 投票:0回答:1

我正在尝试使用 multer 将多张图片上传到我的 aws-s3。 我面临的问题是我设法上传了第一个 backgroundImage,它在第二个数组之外,我的意思是。 这是我的结构

const QuizSchema = new mongoose.Schema({
  title: { type: String, required: true, unique: true },
  description: { type: String },
  backgroundImage: { type: String }, 
  questionList: [questionSchema]
})

const questionSchema = new mongoose.Schema({
  questionType: {
    type: String,
    enum: ["True/False", "Quiz"],
    required: true,
  },
  pointType: {
    type: String,
    enum: ["Standard", "Double"],
    required: true,
  },
  backgroundImage: { type: String },
  questionIndex: { type: Number, required: true },
});

我删除了一些结构以使其更具可读性。所以我设法上传并保存了 backgroundImage 的 URL。但是我不能为每个问题上传背景图片。

我的路由器:

router.post(
  "/createQuiz",
  uploadFile.single("backgroundImage"),
  verifyToken,
  createQuiz
);

我的上传文件中间件:

const storage = multer.memoryStorage();
dotenv.config();
export const uploadFile = multer({ storage });

我的测验控制器

// Creating a random image name
const randomImageName = (bytes = 32) =>
  crypto.randomBytes(bytes).toString("hex");

const imageName = randomImageName();

// Creating a new Quiz
export const createQuiz = async (req, res) => {
  const user = await User.findById(req.user.id);

  //Resize Image
  const buffer = await sharp(req.file.buffer)
    .resize({ height: 500, width: 500, fit: "contain" })
    .toBuffer();

  const params = {
    Bucket: bucketName,
    Key: imageName,
    Body: buffer,
    ContentType: req.file.mimetype,
  };

  const command = new PutObjectCommand(params);
  await s3.send(command);

  const { title, description, categories, questionList } = req.body;
  const backgroundImage = imageName;

  const quiz = new Quiz({
    title,
    description,
    backgroundImage,
    categories,
    creatorId: req.user.id,
    creatorName: user.firstName + " " + user.lastName,
    numberOfQuestions: questionList.length,
    questionList,
    dateCreated: new Date().toISOString(),
  });
  try {
    const newQuiz = await quiz.save();
    res.status(201).json(newQuiz);
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

提前致谢, P.S 我删除了我为问题列表尝试的所有内容,因为它不起作用。

javascript amazon-web-services amazon-s3 multer multer-s3
1个回答
0
投票

可以使用multer的array(fieldName[, maxCount])方法来处理多个文件的上传。为此,您需要修改路由器、中间件和控制器。

  1. 修改您的路由器以使用 uploadFile.array() 而不是 uploadFile.single():
router.post(
  "/createQuiz",
  uploadFile.array("backgroundImage"),
  verifyToken,
  createQuiz
);
  1. 更新您的控制器以处理多个文件并循环遍历 req.files 数组以处理每个图像:
export const createQuiz = async (req, res) => {
  const user = await User.findById(req.user.id);

  const quizImageURLs = [];

  for (const file of req.files) {
    const imageName = randomImageName();
    const buffer = await sharp(file.buffer)
      .resize({ height: 500, width: 500, fit: "contain" })
      .toBuffer();

    const params = {
      Bucket: bucketName,
      Key: imageName,
      Body: buffer,
      ContentType: file.mimetype,
    };

    const command = new PutObjectCommand(params);
    await s3.send(command);

    quizImageURLs.push(imageName);
  }

  const { title, description, categories, questionList } = req.body;
  const backgroundImage = quizImageURLs.shift(); // Remove the first image URL as the backgroundImage

  // Update the backgroundImage for each question
  questionList.forEach((question, index) => {
    question.backgroundImage = quizImageURLs[index];
  });

  const quiz = new Quiz({
    title,
    description,
    backgroundImage,
    categories,
    creatorId: req.user.id,
    creatorName: user.firstName + " " + user.lastName,
    numberOfQuestions: questionList.length,
    questionList,
    dateCreated: new Date().toISOString(),
  });

  try {
    const newQuiz = await quiz.save();
    res.status(201).json(newQuiz);
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

这将处理所有上传的图像并保存测验和问题的背景图像。

请注意,这假设 req.files 数组中的第一个图像是测验的背景图像,后续图像是问题列表中每个问题的背景图像。确保在发出请求时以正确的顺序发送图像。

更新: 看起来您正在将问题列表作为 JSON 字符串发送到 formData 中,因此您需要在使用 forEach 方法之前将其解析回控制器中的数组。此外,确保每个问题的图像都附加到 formData。

在您的前端代码中,将每个问题的 backgroundImage 附加到 formData。确保主背景图像是第一个要附加的图像。

// Append the main backgroundImage to the quiz data
quizData.append("backgroundImage", values.backgroundImage);

// Append each question's backgroundImage to the quiz data
values.questionList.forEach((question, index) => {
  quizData.append(`backgroundImage${index + 1}`, question.backgroundImage);
});

// Append the questionList array as a JSON string
quizData.append("questionList", JSON.stringify(values.questionList));

在您的控制器中,在使用 forEach 方法之前将问题列表解析回数组:

const { title, description, categories, questionList: questionListJSON } = req.body;
const questionList = JSON.parse(questionListJSON);

通过这些更改,您的控制器应该具有正确的数据,并且 quizImageURLs 应该包含测验及其问题的所有背景图像 URL。确保从前端发送正确数量的图像以匹配问题列表中的问题数量。

© www.soinside.com 2019 - 2024. All rights reserved.