0

I am trying to POST a file from a front-end index.html to an Express Server running in the background. The API is then supposed to save the file into Firebase Storage. The server is running properly and it is receiving the POST, but there is no data in the req.body.

index.html - Front-end

<form method="POST" id="form">
 <input type="file" id="file" name="file" multiple>
 <input type="submit">
</form>

<script>
 const form = document.querySelector('#form')

 const postFile = (e) => {
  e.preventDefault()
  const header = { "Content-Type": "multipart/form-data" }

  let formData = new FormData()
  formData.append('file', this.file.files[0])

  fetch('http://localhost:3003/file', {
   method: form.method,
   headers: header,
   body: formData
  }).then(() => {
      alert("OK")
  }).catch(() => {
      alert("Nope")
  })
 }

 form.addEventListener('submit', (e) => postFile(e))
</script>

server.js - Back-end (Incomplete)

const server = express()
const routes = require('./routes')

server.use(cors())
server.use(express.urlencoded({
    limit: '50mb',
    extended: true
}))
server.use(express.json({
    limit: '50mb',
    extended: true
}))
server.use(routes)
server.listen(3003)

fileController.js - Back-end (Incomplete)

exports.addFile = async (req, res) => {
    try {
        console.log(req.body)

        return res.status(200).send({
            message: "Ok"
        })
    } catch (e) {
        return res.status(500).send({
            message: e.message
        })
    }

When I console.log(this.file.files[0]) before fetching it actually returns the File as it is supposed to, but in the server is just an empty array. Front-end console.log; Server console.log

  • Which express and cors npm packages (and version numbers) are you using on the server side? – Wezelkrozum May 30 '20 at 15:02
  • I think this is the answer you are looking for: https://stackoverflow.com/questions/49067423/multipart-form-data-post-method-using-express-js?answertab=active#tab-top – Wezelkrozum May 30 '20 at 15:12
  • Another hint. When you've add multer and added upload.single('file') to your post handler in the server you should remove the content-type header, because the browser adds that header automatically. And manually adding the Content-Type header to multipart/form-data still requires you to set the boundary. But you don't need that. – Wezelkrozum May 30 '20 at 15:46
  • @Wezelkrozum Thank you! That worked for this issue. The files are saved with a weird filename though, but that's ok. Now I'm trying to figure out how to store it into Firebase Storage, since firebase.storage() doesn't work as stated in the docs. Thx anyway – Rafael Scherer May 30 '20 at 17:12
  • I'm glad I was able to help you on your way. I haven't used Firebase Storage yet. So good luck on the last step of getting the file stored into Filebase Storage! – Wezelkrozum May 30 '20 at 21:16

1 Answers1

0

Ok, problem is solved. As Wezelkrozum pointed out, I could've used multer (npm install --save multer)

Changes Applied:

index.html

<form method="POST" id="form" **enctype="multipart/form-data"**>
 <input type="file" id="file" name="file" multiple>
 <input type="submit">
</form>

<script>
 const form = document.querySelector('#form')

 const postFile = (e) => {
  e.preventDefault()

  let formData = new FormData()
  formData.append('file', this.file.files[0])

  fetch('http://localhost:3003/file', { //Removed the Headers
   method: form.method,
   body: formData
  }).then(() => {
      alert("OK")
  }).catch(() => {
      alert("Nope")
  })
 }

 form.addEventListener('submit', (e) => postFile(e))
</script>

routes.js

const express = require('express')
const multer = require('multer')
const routes = express.Router()

const upload = multer({dest: 'uploads/'}) //Folder where the temp file is stored

routes.post('/file', upload.single('file'), fileController.addFile) //This is for one file only
module.exports = routes

Then in the Controller the file properties will come as req.file, just like:

let file = req.file

EDIT:

To get the actual file content you must use:

npm install fs

fs.readFileSync(file.path)

It will return a buffer of the file, needed for any operation related with File or Blob