Solution 1 :

Try this steps to solve the problem

  1. remove the headers on the request method

axios.post('/send', data)

  1. uncomment the form data part
const formData = new FormData();
formData.append('data', data);
  1. on your multer middle ware must match the name of the data

upload.single('data') // instead of "fileInput"

Solution 2 :

I think it will be useful for someone else, i fixed the problem by removing the frontend code for grabbing the forms:

index.js

const sendMail = () => {
  const email = getIds('email').value;
  const subject = getIds('subject').value;
  const myBtn = getIds('btn');
  const htmlFormat = quill.root.innerHTML;
  const content = (getIds('content').value = htmlFormat);
  const data = {
    email,
    subject,
    content,
  };
  // const formData = new FormData();
  // formData.append('data', data);

  console.log(data);
  myBtn.disabled = true;
  axios
    .post('/send', data, {
      headers: {
        'Content-Type': 'application/json',
      },
    })
    .then((res) => {
      myBtn.disabled = false;
      form.reset();
      quill.setContents([{ insert: 'n' }]);
      M.toast({ html: 'Email Sent!', classes: '' });
      console.log(res);
    })
    .catch((err) => {
      myBtn.disabled = false;
      M.toast({ html: `Error: ${err.message}` });
      console.log(err);
    });
};

form.addEventListener('submit', (e) => {
  e.preventDefault();
  sendMail();
});

and let Multer package do it job, by doing this: req.file it now available and i also made sure i have the name attribute on all inputs

And I also remove this line

const filePath = fs.createReadStream(file.path);

Problem :

I am trying to upload an a file using multer. Every other data is posting but I am getting undefined when it comes to file input. I’m trying to send an attachment to Mail using sendGrid API.

Html

<form id="form" enctype="multipart/form-data">
  <div>
    <div class="input-field">
      <input id="email" type="email" required />
      <label class="active" for="email">To </label>
    </div>

    <div class="file-field input-field">
      <div class="btn btn-small">
        <span><i class="small material-icons">attach_file</i></span>
        <input type="file" id="fileInput" name="fileInput" />
      </div>
      <div class="file-path-wrapper">
        <input class="file-path" type="text" placeholder="attach a file?">
      </div>
    </div>

    <div class="input-field">
      <input id="subject" type="text" required />
      <label class="active" for="subject">Subject</label>
    </div>

    <div class="input-field hide">
      <input id="content" type="text" />
      <label class="active" for="content"></label>
    </div>
  </div>

  

  <div class="w-md">
    <div id="toolbar"></div>
    <div id="editor"></div>
  </div>

  <div class="mt-2 mb-2 center">
    <button class="btn waves-effect waves-light btn-small" id="btn" type="submit">Submit
      <i class="small material-icons right">send</i>
    </button>
  </div>
</form>



index.js

    const sendMail = () => {
      const email = getIds('email').value;
      const subject = getIds('subject').value;
      const myBtn = getIds('btn');
      const htmlFormat = quill.root.innerHTML;
      const content = (getIds('content').value = htmlFormat);
      const data = {
        email,
        subject,
        content,
      };
      // const formData = new FormData();
      // formData.append('data', data);
    
      console.log(data);
      myBtn.disabled = true;
      axios
        .post('/send', data, {
          headers: {
            'Content-Type': 'application/json',
          },
        })
        .then((res) => {
          myBtn.disabled = false;
          form.reset();
          quill.setContents([{ insert: 'n' }]);
          M.toast({ html: 'Email Sent!', classes: '' });
          console.log(res);
        })
        .catch((err) => {
          myBtn.disabled = false;
          M.toast({ html: `Error: ${err.message}` });
          console.log(err);
        });
    };
    
    form.addEventListener('submit', (e) => {
      e.preventDefault();
      sendMail();
    });

I don’t know if i’m actually doing something wrong here, that is why i commented formData.

app.js (nodejs backend)

...
const multer = require('multer');
// const upload = multer({ dest: './uploads/' });
const multerStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, './uploads/');
  },
  filename: (req, file, cb) => {
    cb(
      null,
      `${file.fieldname}-${Date.now()}-${path.extname(file.originalname)}`
    );
  },
});

const upload = multer({ storage: multerStorage });

app.post('/send', upload.single('fileInput'), async (req, res) => {
  const sendMail = () => {
    return new Promise(async (resolve, reject) => {
      // pathToAttachment = `${__dirname}/attachment.pdf`;
      // attachment = fs.readFileSync(pathToAttachment).toString('base64');
      const file = req.file;
      const { email, content, subject } = req.body;
      console.log(file);
      // returns undefined
      console.log(req.body);
      const filePath = fs.createReadStream(file.path);

      pathToAttachment = `${filePath}`;
      attachment = fs.readFileSync(pathToAttachment).toString('base64');
      if (!file) {
        return res.json({
          message: 'Select a file',
        });
      } else {
        try {
          setApiKey();
          const msg = {
            to: [`${email}`],
            from: '[email protected]', // Use the email address or domain you verified above
            subject: `${subject}`,
            html: `${content}`,
            attachments: [
              {
                content: attachment,
                filename: file[0].originalname,
                type: file.mimetype,
                disposition: 'attachment',
              },
            ],
          };
          const result = await sgMail.send(msg);
          resolve(result);
          console.log('Message sent!');
        } catch (err) {
          console.log('Error in sendEmail: ', err.response.body);
          reject(err.response.body);
        }
      }
    });
  };
  try {
    await sendMail();
    res.json({
      message: 'Message Sent!',
    });
  } catch (error) {
    res.status(400).json({
      message: 'Something went wrong',
    });
  }
});

// Setting PORT from config
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server Started on ${PORT}`));

I know this question has been asked so many times, i actually don’t know where i’m doing it wrong.

Comments

Comment posted by aRvi

did you try using postman

Comment posted by scotch.io/tutorials/express-file-uploads-with-multer]

please do check this link: [

Comment posted by AbdulAzeez Olanrewaju

Cannot read property ‘path’ of undefined: Post man and it is because it can’t read file obviously

Comment posted by lizen shakya

should be sending data in content-type: multipart/form-data

By