點燈坊

失くすものさえない今が強くなるチャンスよ

Upload File with Other Data

Sam Xiao's Avatar 2022-08-19

When we POST file to the server, we can also POST other data.

Version

Node 16.16.0
Express 4.17.1
Alpine 3.10.3

Alpine

data001

Upload single file by Alpine and Express.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/alpinejs" defer></script>
    <title>Upload</title>
  </head>
  <body x-data="fileUpload">
    <input x-ref="upload" type="file" />
    <button @click="onClick">Upload</button>
    <div x-text="resMsg"></div>
  </body>
  <script>
    let fileUpload = {
      resMsg: '',
      async onClick() {
        let newFileName = Date.now() + '-' + Math.round(Math.random() * 1E9)

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

        try {
          let res = await fetch(`http://localhost:8080/upload`, {
            method: 'POST',
            body: formData,
          })

          let data = await res.json()
          this.resMsg = data.message
        } catch (e) {
          console.error(e)
        }
      },
    }
  </script>
</html>

Line 8

<body x-data="fileUpload">
  <input x-ref="upload" type="file" />
  <button @click="onClick">Upload</button>
  <div x-text="resMsg"></div>
</body>
  • x-data:with fileUpload Object to control the component
  • x-ref:to set the name for the DOM element
  • @click:upload the file to the server
  • x-text:display the result message

Line 17

let newFileName = Date.now() + '-' + Math.round(Math.random() * 1E9)
  • Determine a random file name

Line 19

let formData = new FormData()
formData.append('newFileName', newFileName)
formData.append('file', this.$refs.upload.files[0])
  • fetch() accepts FormData as argument for body
  • Append newFileName key for other POST data
  • Append file key for uploaded file

Line 23

try {
  let res = await fetch(`http://localhost:8080/upload`, {
    method: 'POST',
    body: formData,
  })

  let data = await res.json()
  this.resMsg = data.message
} catch (e) {
  console.error(e)
}
  • Use fetch() API with method POST and body formData
  • response.json()fetch() returns Promise with Response Object, use json() to convert Response Object to JSON Object

Express

data000

Server gets the newFileName from the client.

import express, { json } from 'express'
import cors from 'cors'
import multer from 'multer'

let app = express()
app.use(cors())
app.use(json())

let opts = multer({ dest: 'uploads/' }).single('file')

app.post('/upload', opts, (req, res) => {
  let { body: { newFileName }} = req
  console.log('newFileName', newFileName)

  res.json({ message: 'Successfully uploaded files' })
})

app.listen(8080, () => {
  console.log('Node listen on port: 8080')
})

Line 1

import express, { json } from 'express'
import cors from 'cors'
import multer from 'multer'
  • Import expresscors and multer

Line 5

let app = express()
  • Create app Object for Express

Line 6

app.use(cors())
  • Create cors middleware by cors()
  • Use cors middleware by Express

Line 7

app.use(json())
  • Create json middleware by json(). This is a built-in middleware by Express
  • Use json middleware by Express

Line 9

let opts = multer({ dest: "uploads/" }).single("file")
  • Create opts Object for Multer
  • dest:set folder to place files
  • single:upload single file by Multer, the argument for single() must depend on the name for the input specified in formData in Alpine

Line 11

app.post('/upload', opts, (req, res) => {
  let { body: { newFileName }} = req
  console.log('newFileName', newFileName)

  res.json({ message: 'Successfully uploaded files' })
})
  • Create /upload POST with Multer options
  • Use Object Destructuring to destructure req Object to get other POST data
  • Return JSON Object with successful message

Line 16

app.listen(8080, () => {
  console.log('Node listen on port: 8080')
})
  • Express listens on port 8080

Conclusion

  • Since Multer uses POST, we can also POST other data along with POST action