node使用multer進行檔案上傳

2023-03-12 12:00:15

開場白

在平時的業務中,我們很多使用都會有檔案上傳這個功能。
今天分享一下使用 node+element-ui實現一下檔案上傳。
請個人大佬指點一番~~~。批評的時候稍微輕一點。
畢竟我心裡承受能力弱地一批,一不高興就喜歡....

使用 element-ui庫el-upload元件fil型別上傳

前端上傳檔案的時候,我們通常file物件。
較小的圖片的當然也可以使用base64的方式進行上傳。
等會我們將會將file轉化為base64。
file物件傳參的時候是這樣的 file:file(二進位制物件)   
並且'Content-type': 'multipart/form-data'
下面我們使用 element-ui 的el-upload 元件進行檔案上傳.
我們會使用 http-request 自定義事件覆蓋原來的事件。
請看下面的程式碼
<template>
  <div>
    <h2>檔案上傳</h2>
    <el-upload class="upload-demo" action="https"  
       :http-request="uploadFile">
      <el-button size="small" type="primary">點選上傳</el-button>
    </el-upload>
  </div>
</template>
<script>
import axios from 'axios'
export default {
  methods: {
    uploadFile(file) {
      console.log('file物件', file)
      axios.post('http://127.0.0.1:666/upload/upload',
        {
          file:file
        },  {
            'Content-type': 'multipart/form-data'
          }
      ).then(function (response) {
        console.log(response);
      }).catch(function (error) {
        console.log(error);
      });
    }
  }
}
</script>
寫過很多檔案上傳的的小夥伴。
你們覺得可以上傳成功嗎? 
會是file:file(二進位制)物件嗎?
憑藉自己的感覺想一分鐘,然後下滑


為什麼傳參的是 file:{...},而不是file:file(二進位制)

有的小夥伴會說 你傳的時候不應該是file,應該是file.file
因為從你剛剛的截圖來看應該是:file.file才是我們需要的。
感覺說的有道理,我們嘗試一下。

使用FormData來解決這個問題

FormData是XMLHttpRequest提供的一個介面物件,
用以將資料編譯成鍵值對,以便於XMLHttpRequest來傳送資料。
建立一個 FormData物件,並新增屬性。
FormData 可以通過 append(key, value)來新增資料。
上面說了 FormData的簡單介紹。
並沒有說為啥FormData可以使用解決這個這個問題?
那為什麼FormData可以解決這個問題了?
因為:
File 介面基於 Blob,繼承 blob 功能並將其擴充套件為支援使用者系統上的檔案。
你可以通過 Blob() 建構函式建立一個 Blob 物件。
而 FormData 物件附加 File 或 Blob 型別的檔案,所以我們可以新增。
<script>
import axios from 'axios'
export default {
  methods: {
    uploadFile(file) {
      let formdata = new FormData();
      console.log(file);
      formdata.append("file", file.file);
      axios.post('http://127.0.0.1:666/upload/upload',
        formdata,  {
            'Content-type': 'multipart/form-data'
          }
      ).then(function (response) {
        console.log(response);
      }).catch(function (error) {
        console.log(error);
      });
    }
  }
}
</script>

將file轉為base64

<template>
  <div>
    <!-- accept 接收圖片格式 -->
    <input type="file" title="" ref="inputRef" 
    accept=".jpeg,.png, .gif,.jpg" @change="Upload">
  </div>
</template>
<script>
import axios from 'axios'
export default {
  methods: {
    // 檔案上傳被觸發
    Upload(event) {
      const flie = event.target.files[0]; //直接獲取的就是file物件
      this.fileChangeBase64(flie).then(backres => {
        console.log('base64', backres)
        // 上傳成功後的處理,清除input中value值,否則只相同檔案只能夠上傳一次
        // this.$refs.inputRef.value = ""; 在合適的時候使用
      }).catch(err => {
        console.log('err', err )
      })
    },
    // 將file物件轉化為base64
    fileChangeBase64(file) {
      return new Promise((resolve, reject) => {
        //FileReader類就是專門用來讀檔案的,我們現在建立一個
        const reader = new FileReader()
        // 它的本質就是圖片的二進位制資料, 進行base64加密後形成的一個字串.
        reader.readAsDataURL(file)
        // 成功返回對應的資訊,reader.result一個base64
        reader.onload = () => resolve(reader.result)
        // 失敗返回失敗的資訊
        reader.onerror = error => reject(error)
      })
    }
  }
}
</script>
需要注意的一點,我這裡是將file轉為base64哈。
base64將不會不能被multer處理的哈~或者說不能夠處理

node中介軟體 multer 的簡單介紹

前端程式碼已經寫好了,現在我們開始寫後端的程式碼,後端我們使用node+express
multer 是一個 node.js 中介軟體。
它用於處理 multipart/form-data 型別的表單資料,它主要用於上傳檔案。
需要注意的是: multer 不會處理任何非 multipart/form-data 型別的表單資料。
換一句換說:前端必須這樣設定型別 'Content-type': 'multipart/form-data'

guthub官方解釋連結
https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md

下載 multer

前端程式碼寫好了,現在我們開始藉助node來實現後端的程式碼
我們使用 multer 來進行檔案傳
第一步:先下載 multer 模組
npm i express multer -S
我下載的時候是1.4.5版本

fileupload.js檔案

// 引入express
var express = require('express')
//新增路由模組
var router = express.Router()
// 檔案上傳需要的模組
var multer=require('multer')
// 設定路徑和檔名
var storage = multer.diskStorage({
  //上傳檔案到伺服器的儲存位置
  destination: 'public/upload',
  filename: function (req, file, callback) {
    //上傳的檔案資訊
    console.log('file', file) 
    /**
     * file {
        fieldname: 'file',
        originalname: 'JRMW5Y~E5B%UO4$EZ)[)XLR.png',
        encoding: '7bit',
        mimetype: 'image/png'
      }
    */
    // 將字串分割成為陣列,以點.的形式進行分割。返回的是一個陣列
    var fileFormat = (file.originalname).split('.')
    // 獲取時間戳
    var filename = new Date().getTime()
    // 檔案的命名為:時間戳 + 點 + 檔案的字尾名
    callback(null, filename + "." + fileFormat[fileFormat.length-1])
  }
})
var upload = multer({
  storage
})
router.post('/upload', upload.single('file'), (req, res) => {
  res.send({ code:'0', msg:'上傳成功'})
})
module.exports = router;

app.js 引入註冊路由

// 引入
var uploadRouter = require('./routes/fileupload');
// ... 其他程式碼....
//註冊介面字首/upload
app.use('/upload', uploadRouter);

//這個時候介面就是 /upload/upload

需要注意的點

1. 需要注意的點:upload.single('key') 必須要與前端中
formData.append("file", flie)key鍵名保持一致。

2. 為什麼不直接使用前端傳遞傳來的名稱?
因為有可能名稱會重複,這樣不好。

3. 因為前端上傳檔案的時候使用change事件進行監聽的。
注意在合適的時候清除它的value值,否者上傳相同的檔案change事件不會被觸發