File data(Image, pdf) is not getting pushed into the MongoDB array

Issue

Whenever I upload the new file from the postman it overwrites existing file and save one and only uploaded file.

I have tried document.push method but it logs the error that "TypeError: documents.push is not a function" But when I log console.log(documents) it logs in an array. Am I doing something wrong?

The multer function to handle file uploading:

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "./src/uploads/");
  },
  filename: function (req, file, cb) {
    cb(
      null,
      file.fieldname + "-" + Date.now() + path.extname(file.originalname)
    );
  },
});

var upload = multer({
  storage: storage,
  fileFilter: function (req, file, cb) {
    var filetypes = /jpeg|jpg|png|pdf/;
    var mimetype = filetypes.test(file.mimetype);

    var extname = filetypes.test(path.extname(file.originalname).toLowerCase());

    if (mimetype && extname) {
      return cb(null, true);
    }
    cb("Please upload valid file");
  },
}).array("documents");

The uploadDocument service file:

exports.uploadDocuments = async (id, documents, file) => {
  let files = documents.push(file);
  let document = await User.findByIdAndUpdate(
    { _id: id },
    { $set: { documents: files, registration_process_value: 99 } },
    { new: true }
  );
  return document;
};

The userController to upload the file:

exports.updateDocuments = catchAsync(async (req, res) => {
  try {
    check_user = await userService.getUser(req.data.id);
    if (!check_user) return res.status(404).json({ message: "User not found" });
    if (check_user.registration_process_value >= 4) {
      let uploadDocument = await userService.uploadDocuments(
        check_user.id,
        check_user.documents,
        req.files
      );
      return res.status(200).json({ data: uploadDocument });
    }
  } catch (error) {
    return res.status(400).json({ message: error });
  }
});

The documents type is Array in the schema like following:

documents: {
      type: Array,
    }

documents.push(file) is returning a number (like if I console.log(files) after sending the request from the postman then it returns "files -> 2"). It is not pushing the actual data of the file.

Solution

First you push a file into documents and store the new length of the array in files:

let files = documents.push(file);

Then you set the documents field to that array length:

  let document = await User.findByIdAndUpdate(
    { _id: id },
    { $set: { documents: files, registration_process_value: 99 } },
    { new: true }
  );

I assume that you want to store the actual array:

{ $set: { documents: documents, registration_process_value: 99 } }

Instead of using $set to replace the entire documents array, I would suggest using $push:

{
  $set:  { registration_process_value: 99 },
  $push: { documents : file }
}

EDIT: if file is actually an array of file objects, instead of a single object, things change a bit.

If you still want to use push:

documents.push(...file);

With $push, you need to use $each:

{
  $push : { documents : { $each : file } }
}

Answered By – robertklep

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published