點燈坊

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

Upload File with Original File Name

Sam Xiao's Avatar 2022-08-19

Multer default changes the file name of uploaded files. If we want to keep the original file name, we have to write some code.

Version

Node 16.16.0
Express 4.17.1
Alpine 3.10.3

Alpine

original000

Upload a single file by Alpine and Express with the original file name.

<!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 formData = new FormData()
        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 formData = new FormData();
formData.append("file", this.$refs.upload.files[0]);
  • fetch() accepts FormData as an argument for body
  • Append the file key for the uploaded file

Line 20

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

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

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

let storage = diskStorage({
  destination(req, file, cb) {
    cb(null, 'uploads')
  },
  filename(req, file, cb) {
    cb(null, file.originalname)
  },
})

let opts = multer({ storage }).single('file')

app.post('/upload', opts, (req, res) => {
  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, { diskStorage } 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 storage = diskStorage({
  destination(req, file, cb) {
    cb(null, 'uploads')
  },
  filename(req, file, cb) {
    cb(null, file.originalname)
  },
})
  • Use diskStorage() to create storage Object for Multer options
  • destination:determine within which folder the uploaded files should be stored
  • filename:determine what the file should be named inside the folder

Line 18

let opts = multer({ storage }).single('file')
  • Create opts Object for Multer
  • dest:use storage as the key for options
  • single:upload single file by Multer, the argument for single() must depend on the name for the input specified in formData in Alpine

Line 20

app.post('/upload', opts, (req, res) => {
  res.json({ message: 'Successfully uploaded files' })
})
  • Create /upload POST with Multer options
  • Return JSON Object with successful message

Line 24

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

Conclusion

  • If we want to control the file name of the uploaded file, the disk storage engine gives us full control on storing files to disk