首頁  >  文章  >  web前端  >  Nodejs+express中間件實作檔上傳

Nodejs+express中間件實作檔上傳

青灯夜游
青灯夜游轉載
2021-04-16 11:00:492281瀏覽

本篇文章給大家詳細介紹Nodejs檔案上傳的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

Nodejs+express中間件實作檔上傳

筆者用nodejs做專案時需要用到檔案上傳的功能,在網路上搜尋了很多教學,找到了一個express的中間件,用來處理 multipart/form-data類型的表單數據,可以很方便的將表單中的檔案資料儲存到伺服器。

介紹


multer是一個node.js檔案上傳中間件,它是在busboy的基礎上開發的,上傳的表單資料必須是multipart/form- data類型,不然會報錯。 【相關推薦:《nodejs 教學》】

簡單的用法


定義記憶體

Multer作為express的一個中間件,我們可以很方便的自訂上傳的檔案目錄以及已儲存的檔案名稱。先看一個最簡單的用法,demo1地址

var express = require('express');
var multer = require('multer');
var app = express();

var upload = multer({
    storage: multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, './uploads/');
        },
        filename: function (req, file, cb) {
            //file.originalname上传文件的原始文件名
            var changedName = (new Date().getTime())+'-'+file.originalname;
            cb(null, changedName);
        }
    })
});

我們先建立了一個upload對象,這個對像中destination函數用來定義上傳檔案的儲存的資料夾;filename函數用來修改上傳檔案儲存到伺服器的檔案名稱,這裡我們我們加上一個時間戳簡單區分一下。這兩個函數都是透過回調函數來實現的。每次上傳的時候這兩個函數都會被呼叫一次,如果是多個檔案上傳,那個這兩個函數就會呼叫多次,呼叫順序是先呼叫destination,然後呼叫filename。

在兩個函數中都會有一個file對象,表示目前上傳的檔案對象,有以下幾個屬性:

  • fieldname:上傳的字段名稱
  • originalname:上傳的檔案名稱
  • encoding:檔案的編碼類型
  • mimetype:檔案的MIME類型

附:一些常用的MIME類型

定義路由回呼

#
//单个文件上传
app.post('/upload/single',upload.single('singleFile'),(req,res)=>{
    console.log(req.file);
    res.json({
        code: '0000',
        type:'single',
        originalname: req.file.originalname
    })
});

//多个文件上传
app.post('/upload/multer',upload.array('multerFile'),(req,res)=>{
    console.log(req.files);
    let fileList = [];
    req.files.map((elem)=>{
        fileList.push({
            originalname: elem.originalname
        })
    });
    res.json({
        code: '0000',
        type:'multer',
        fileList:fileList
    });
});

在express定義路由的回呼函數時,把定義好了的upload物件作為中間件添加進去。如果是單一檔案就用single方法,如果是多個檔案就用array方法,這兩個方法都需要傳一個頁面上定義好的欄位名稱。

在路由的回呼函數中,request物件已經有了file屬性(單一檔案上傳)或files屬性(多個檔案上傳),files屬性是一個數組,數組的每個物件都有以下屬性:

  • fieldname:上傳的欄位名稱
  • originalname:上傳的檔案名稱
  • encoding:檔案的編碼類型
  • mimetype:檔案的MIME類型
  • destination:儲存的目錄(和destination回呼函數中的目錄名稱一致)
  • filename:已儲存的檔案名稱(和filename回呼函數中的檔案名稱一致)
  • path:已儲存的相對路徑
  • size:檔案的大小(單位:位元組byte)

  我們可以發現在路由的回呼函數中的file物件比diskStorage中的file物件多了幾個屬性,這是因為在diskStorage中檔案還沒有保存,只能知道檔案的大致屬性;而路由的回呼函數檔案已經在伺服器上保存好了,檔案的儲存路徑以及檔案的大小都是已知的。

混合上傳

有時候我們可能需要用欄位名稱來對上傳的檔案進行一下劃分,比如說上傳多個圖片的時候可能有身分證還有頭像。雖然可以分開放到兩個介面中,但是會產生其他一系列的麻煩事。 multer支援對圖片進行欄位名稱的劃分。 demo3位址

//多字段名上传
let multipleFields = upload.fields([
    {name:'avatar'},
    {name:'gallery', maxCount:3},
]);
app.post('/upload/fields', (req,res)=>{
    multipleFields(req,res,(err) => {
        console.log(req.files);
        if(!!err){
            console.log(err.message);
            res.json({
                code: '2000',
                type: 'field',
                msg:err.message
            })
            return;
        }
        var fileList = [];
        for(let item in req.files){
            var fieldItem = req.files[item];
            fieldItem.map((elem) => {
                fileList.push({
                    fieldname: elem.fieldname,
                    originalname: elem.originalname
                })
            });
        }
        res.json({
            code: '0000',
            type: 'field',
            fileList: fileList,
            msg:''
        })
    });
});

在這邊也有req.files屬性,但是這個屬性不是一個數組,而是一個複雜的對象,這個對像有多個屬性,每個屬性名都是一個字段名,每個屬性下面又是一個數組,數組下面是一個個的文件對象,結構大致如下:

{
    "avatar":[{
        fieldname: "",
        originalname: ""
        //...
    }],
    "gallery":[{
        fieldname: "",
        originalname: ""
        //...
    }]
}

過濾文件上傳


在文件上傳時,有時候會上傳一些我們不需要的文件類型,我們需要把一些不需要的文件給過濾掉。 demo2位址

檔案類型過濾

var upload = multer({
    //...其他代码
    fileFilter: function(req, file, cb){
        if(file.mimetype == 'image/png'){
            cb(null, true)
        } else {
            cb(null, false)
        }
    }
});

  在定義記憶體的時候,新增一個fileFilter函數,用來過濾我們不需要的文件,在回呼函數中我們傳入true/false來代表是否要儲存;如果傳了false,那麼destination函數和filename函數也不會呼叫了。

文件大小和数量过滤

var upload = multer({
    //...其他代码
    limits:{
        //限制文件大小10kb
        fileSize: 10*1000,
        //限制文件数量
        files: 5
    }
});

在定义存储器的时候,新增一个limits对象,用来控制上传的一些信息,它有以下一些属性:

  • fieldNameSize:field 名字最大长度,默认值:100 bytes
  • fieldSize:field 值的最大长度,默认值:1MB
  • fields:非文件 field 的最大数量
  • fileSize:在multipart表单中, 文件最大长度 (字节单位)
  • files:在multipart表单中, 文件最大数量
  • parts:在multipart表单中, part传输的最大数量(fields + files)

在这边我们把fileSize的值设置得小一点,设为10kb方便测试看效果,但是如果这个时候会发现有报错。因为上传的文件大小很容易就会超过10KB,导致有报错出现,我们就需要在路由回调里对错误的情况进行捕获。

//单个文件上传
let singleUpload = upload.single('singleFile');
app.post('/upload/single',(req,res)=>{
    singleUpload(req,res,(err)=>{
        if(!!err){
            console.log(err.message)
            res.json({
                code: '2000',
                type:'single',
                originalname: '',
                msg: err.message
            })
            return;
        }
        if(!!req.file){
            res.json({
                code: '0000',
                type:'single',
                originalname: req.file.originalname,
                msg: ''
            })
        } else {
            res.json({
                code: '1000',
                type:'single',
                originalname: '',
                msg: ''
            })
        }
    });
});

//多个文件上传
let multerUpload = upload.array('multerFile');
app.post('/upload/multer', (req,res)=>{
    multerUpload(req,res,(err)=>{
        if(!!err){
            res.json({
                code: '2000',
                type:'multer',
                fileList:[],
                msg: err.message
            });
        }
        let fileList = [];
        req.files.map((elem)=>{
            fileList.push({
                originalname: elem.originalname
            })
        });
        res.json({
            code: '0000',
            type:'multer',
            fileList:fileList,
            msg:''
        });
    });
});

所有的demo代码都在仓库里,地址:https://github.com/acexyf/multerDemo

更多编程相关知识,请访问:编程入门!!

以上是Nodejs+express中間件實作檔上傳的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除