Search code examples
javascriptreactjsfile-uploadform-data

How do I create a schema to accept array of file objects?


formData array of files:

const noteSubmitHandler = async event => {
  event.preventDefault();
  try {
    const formData = new FormData();

    for (let i = 0; i < attachments.length; i++) {
      formData.append('files[]', attachments[i]);
    }
    formData.append('title', title);

    await sendRequest(
      process.env.REACT_APP_BACKEND_URL + '/notes/create',
      'POST',
      formData,
      { Authorization: 'Bearer ' + auth.token }
    );
    navigate(`/${auth.userId}/notes`);
  } catch (err) { }
};

Input:

<input
  type="file"
  accept=".jpg,.png,.jpeg"
  multiple
  onChange={(e) => setAttachments(e.target.files)}
/>

If I console.log(formData.getAll('files[]')); I get an array of files as expected:

enter image description here

How do I set up the schema on the backend to accept the array? I've tried:

const noteSchema = new Schema({
  title: { type: String, required: true },
  "files[]": [{ type: Object }],
});

and

const noteSchema = new Schema({
  title: { type: String, required: true },
  files: [{ type: Object }],
});

but neither work.


Solution

  • You cant store the file object from Browser into Mongodb but you can extract the properties and store it as an array. Here's how to structure your noteSchema.

    noteSchema:

    const mongoose = require('mongoose');
    
    const fileSchema = new mongoose.Schema({
      name: { type: String, required: true },
      data: { type: Buffer, required: true },
      contentType: { type: String, required: true }
    });
    
    const noteSchema = new mongoose.Schema({
      title: { type: String, required: true },
      files: [fileSchema] // Embed the file data within the Note schema
    });
    
    const Note = mongoose.model('Note', noteSchema);
    
    module.exports = Note;
    

    In this File model, we store the file's name, binary data, and content type. You can adjust the fields in the fileSchema based on your requirements.

    When you receive the files on the server, you should save each file as a separate document in the Note model. You can get files array by using Multer.

    Create Note file:

    const express = require('express');
    const multer = require('multer');
    const router = express.Router();
    const Note = require('../models/note');
    
    const upload = multer({ dest: 'uploads/' });
    
    router.post('/notes/create', upload.array('files'), async (req, res) => {
      try {
        const { title } = req.body;
        const files = req.files;
    
        // Create a new Note instance with embedded file data
        const newNote = new Note({
          title,
          files: files.map(file => ({
            name: file.originalname,
            data: file.buffer,
            contentType: file.mimetype
          }))
        });
    
        // Save the Note instance to the database
        const savedNote = await newNote.save();
    
        res.status(201).json({ note: savedNote });
      } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Server error' });
      }
    });
    
    module.exports = router;