Search code examples
javascriptnode.jsmulter

Unable to load file due to Multipart: Boundary not found


I am trying to upload images from desktop but the error for multipart boundary not found. How to set a boundary for image uploading? This is my first time doing image uploading so please advice.

html event listener when user upload image

document.getElementById('image-file').addEventListener('change', 
    async (e) => {
        const file = e.target.files[0]
        const bodyFormData = new FormData()
        bodyFormData.append('image', file)
        showLoading()
        const data = await uploadProductImage(bodyFormData)
        hideLoading()
        if (data.error) {
          showMessage(data.error)
        } else {
          showMessage('Image Uploaded Successfully.')
          console.log(data)
          document.getElementById('image').value = data.image
        }
      })
  },

api.js - posting action

export const uploadProductImage = async (bodyFormData) => {
  const options = {
    method: 'POST',
    body: bodyFormData,
    headers: {
      'Content-Type': 'multipart/form-data',
    },
  }
  try {
    const response = await fetch(`${apiUrl}/api/uploads`, options)
    const json = await response.json()
    if (response.status !== 201) {
      throw new Error(json.message)
    }
    return json
  } catch (err) {
    console.log('Error in upload image', err.message)
    return { error: err.message }
  }
}

uploadroute.js - for uploading image

import express from 'express'
import multer from 'multer'

const storage = multer.diskStorage({
  destination(req, file, cb) {
    cb(null, 'uploads/')
  },
  filename(req, file, cb) {
    cb(null, `${Date.now()}.png`)
  },
})

const upload = multer({ storage })
const router = express.Router()

router.post('/', upload.single('image'), (req, res) => {
  res.status(201).send({ image: `/${req.file.path}` })
})

export default router

Solution

  • When you're sending a form with fetch in the frontend, don't set Content-Type header yourself. If you do, it won't have the form boundary and the multipart/form-data request will be parsed incorrectly in the backend.

    You can omit the header because the browser will set it for you, which includes a unique boundary. For example:

    • Your header: Content-Type=multipart/form-data;
    • Browser's header: Content-Type=multipart/form-data; boundary=------WebKitFormBoundaryg7okV37G7Gfll2hf--

    In your case:

    const options = {
      method: 'POST',
      body: bodyFormData,
    }
    const response = await fetch(`${apiUrl}/api/uploads`, options)