Multer
是一個node.js中間件,用于處理 multipart/form-data類型的表單數據,主要用于上傳文件。只處理 multipart/form-data 類型的表單數據。
Multer是基于Busboy解析的文件參數信息,獲取fileStream,并通過storage轉存的file.stream.pipe(outStream) //file.stream即fileStream
Multer在解析完請求體后,會向Request對象中添加一個body對象和一個file或files對象(上傳多個文件時使用files對象 )。其中,body對象中包含所提交表單中的文本字段(如果有),而file(或files)對象中包含通過表單上傳的文件。
multer(options).single(name)
上傳單個文件內容,如一次只上傳一張圖片。name為上傳文件時的參數字段名稱。
multer(options).array(name[,maxCount])
適用于同一個字段,一次上傳多個文件的情況,例如選擇多張圖片發送。接受一個以 name?命名的文件數組。可以指定 maxCount 來限制上傳的最大數量。這些文件的信息保存在 req.files。
multer(options).fields(fields)
適用于上傳多個字段的情況。接受指定 fields 的混合文件。這些文件的信息保存在 req.files。fields 是一個對象數組,具有 name 和可選的 maxCount 屬性。
multer(options).none()
接收只有文本域的表單,如果上傳任何文件,會返回 “LIMIT_UNEXPECTED_FILE” 錯誤。
multer(options).any()
接收一切上傳的文件。
Multer 接受一個 options 對象,其中最基本的是 dest/storage?屬性,這將告訴 Multer 將上傳文件保存在哪。如果省略 options 對象,這些文件將保存在內存中,永遠不會寫入磁盤。
1.dest:指定上傳文件的存儲路徑。文件名默認為隨機字符。如果想自定義文件名稱,使用storage屬性代替dest
2.storage:指定上傳文件的存儲路徑和文件名稱。
2-1.DiskStorage 磁盤存儲引擎
磁盤存儲引擎可以讓你控制文件的存儲。有兩個屬性,屬性值都是函數。destination,指定文件存儲的路徑;filename,指定文件的存儲名稱。
multer({storage: multer.diskStorage({
????????//設置存儲路徑
????????destination:(req,file,cb)=>{
????????????console.log("destination:",file);//打印結果如下圖
????????????cb(null,fullPath);
????????},
????????//設置存儲的文件名
????????filename:(req,file,cb)=>{
????????????console.log("filename:",file);//打印結果如下圖
????????????//獲取文件的擴展名
????????????let extname=path.extname(file.originalname);
????????????filename=file.fieldname+"-"+Date.now()+extname;
????????????cb(null,filename);
????????}
????})
});
2-2.MemoryStorage 內存存儲引擎
multer({storage: multer.memoryStorage()})
3.limits: 用來指定一些數據大小的限制等
????????limits:{
???????? files:2, //最多上傳2個文件
????????????fileSize:5120 //設置單個文件最大為 5kb
????????}
4.fileFilter
fileFilter 為一個函數,用來控制什么文件可以上傳以及什么文件應該跳過。
function fileFilter (req, file, cb) {
??// 通過調用cb,用boolean值來指示是否應接受該文件
??// 拒絕這個文件,使用`false`,像這樣:
??cb(null, false)
??// 接受這個文件,使用`true`,像這樣:
??cb(null, true)
??// 如果有問題,你可以總是這樣發送一個錯誤:
??cb(new Error('I don\'t have a clue!'))
}
Busboy
用于解析傳入的HTML表單數據的node.js模塊。
let Busboy = require('busboy');
//通過請求頭信息創建busboy對象??headers - 這些是傳入請求的 HTTP 標頭,由各個解析器使用 preservePath - ?是否應保留請求中文件部分的文件名中的路徑 ?limits - 對傳入數據的各種限制
let busboy = new Busboy({ headers: req.headers });
//將流鏈接到busboy對象
req.pipe(busboy);
//此事件由找到的每個文件字段發出
busboy.on('file', function (filedname, file, filename, encoding, mimetype) {//(字段名,文件,文件名,傳輸編碼,mime類型)
????//創建一個可寫流
????let writeStream = fs.createWriteStream('./upload/' + filename);
????//監聽data事件,接收傳過來的文件,如果文件過大,此事件將會執行多次,此方法必須寫在file方法里
????file.on('data', function (data) {
????????writeStream.write(data);
????})
????//監聽end事件,文件數據接收完畢,關閉這個可寫流
????file.on('end', function (data) {
????????writeStream.end();
????});
});
????//監聽finish完成事件,完成后重定向到百度首頁
????busboy.on('finish', function () {
????????res.writeHead(303, { Connection: 'close', Location: 'http://www.baidu.com/' });
????????res.end();
????});
});
//此事件由找到的每個新的非文件字段發出
busboy.on('field', (name, val, info) => {
??????console.log(`Field [${name}]: value: %j`, val);
????});