Nest.js使用multer實現(xiàn)文件上傳功能
項目創(chuàng)建與配置
新建 nest 項目:
nest new nest-multer-upload -p npm
安裝下 multer 的 ts 類型的包:
npm install @types/multer -D
讓 nest 服務(wù)支持跨域:

單文件上傳
添加一個 handler:
@Post('aaa')
@UseInterceptors(
FileInterceptor('aaa', {
dest: 'uploads',
}),
)
uploadFile(@UploadedFile() file: Express.Multer.File, @Body() body) {
console.log('body', body);
console.log('file', file);
}
這里使用 FileInterceptor 提取請求中的 aaa 字段,并通過 UploadedFile 裝飾器將其作為參數(shù)傳遞。
當(dāng)我們運行 nest start --watch 的時候,uploads 文件夾就會創(chuàng)建。
前端代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
<input id="fileInput" type="file" multiple />
<script>
const fileInput = document.querySelector('#fileInput')
async function formData() {
const data = new FormData()
data.set('name', 'Yun')
data.set('age', 20)
data.set('aaa', fileInput.files[0])
const res = await axios.post('http://localhost:3000/aaa', data)
console.log(res)
}
fileInput.onchange = formData
</script>
</body>
</html>
服務(wù)端就打印了 file 對象和 body 字段,并且文件也保存到了 uploads 目錄:


多文件上傳
@Post('bbb')
@UseInterceptors(
FilesInterceptor('bbb', 3, {
dest: 'uploads',
}),
)
uploadFiles(
@UploadedFiles() files: Array<Express.Multer.File>,
@Body() body,
) {
console.log('body', body);
console.log('files', files);
}
把 FileInterceptor 換成 FilesInterceptor,把 UploadedFile 換成 UploadedFiles,都是多加一個 s。
前端代碼:
async function formData2() {
const data = new FormData()
data.set('name', 'Yun')
data.set('age', 20)
;[...fileInput.files].forEach(item => {
data.append('bbb', item)
})
const res = await axios.post('http://localhost:3000/bbb', data, {
headers: { 'content-type': 'multipart/form-data' },
})
console.log(res)
}
這樣就可以上傳多文件了:

如果有多個文件的字段,和 multer 里類似,使用這種方式來指定:
@Post('ccc')
@UseInterceptors(FileFieldsInterceptor([
{ name: 'aaa', maxCount: 2 },
{ name: 'bbb', maxCount: 3 },
], {
dest: 'uploads'
}))
uploadFileFields(@UploadedFiles() files: { aaa?: Express.Multer.File[], bbb?: Express.Multer.File[] }, @Body() body) {
console.log('body', body);
console.log('files', files);
}
前端代碼:
async function formData3() {
const data = new FormData()
data.set('name', 'Yun')
data.set('age', 20)
data.append('aaa', fileInput.files[0])
data.append('aaa', fileInput.files[1])
data.append('bbb', fileInput.files[2])
data.append('bbb', fileInput.files[3])
const res = await axios.post('http://localhost:3000/ccc', data)
console.log(res)
}
后端收到了上傳的 aaa、bbb 的文件:

如果不知道前端上傳字段,哪些是用于文件上傳的字段,可以使用 AnyFilesInterceptor:
@Post('ddd')
@UseInterceptors(AnyFilesInterceptor({
dest: 'uploads'
}))
uploadAnyFiles(@UploadedFiles() files: Array<Express.Multer.File>, @Body() body) {
console.log('body', body);
console.log('files', files);
}
前端代碼:
async function formData4() {
const data = new FormData()
data.set('name', 'Yun')
data.set('age', 20)
data.set('aaa', fileInput.files[0])
data.set('bbb', fileInput.files[1])
data.set('ccc', fileInput.files[2])
data.set('ddd', fileInput.files[3])
const res = await axios.post('http://localhost:3000/ddd', data)
console.log(res)
}
同樣識別出了所有 file 字段:

這就是 Nest 上傳文件的方式。
自定義存儲
import * as multer from 'multer';
import * as fs from 'fs';
import * as path from 'path';
const storage = multer.diskStorage({
// 自定義目錄
destination: function (req, file, cb) {
try {
fs.mkdirSync(path.join(process.cwd(), 'my-uploads'));
} catch (e) {}
cb(null, path.join(process.cwd(), 'my-uploads'));
},
// 自定義文件
filename: function (req, file, cb) {
const uniqueSuffix =
Date.now() +
'-' +
Math.round(Math.random() * 1e9) +
'-' +
file.originalname;
cb(null, file.fieldname + '-' + uniqueSuffix);
},
});
export { storage };
然后在 controller 使用這個 storage:



其實 Nest 上傳文件的方式就是對 multer 做了一層簡單的封裝。
文件校驗
此外我們還可能對上傳文件的大小,類型做限制。這部分可以放在 pipe 做。
我們生成一個 pipe:
nest g pipe file-size-validation-pipe --no-spec --flat
添加檢查文件大小的邏輯,大于 10k 就拋出異常,返回 400 的響應(yīng):
import {
PipeTransform,
Injectable,
ArgumentMetadata,
HttpException,
HttpStatus,
} from '@nestjs/common';
@Injectable()
export class FileSizeValidationPipe implements PipeTransform {
transform(value: Express.Multer.File, metadata: ArgumentMetadata) {
if (value.size > 10 * 1024) {
throw new HttpException('文件大于 10k', HttpStatus.BAD_REQUEST);
}
return value;
}
}
加到 UploadedFile 的參數(shù)里:

當(dāng)上傳一個圖片大于 10k 的時候:

但像文件大小、類型的校驗這種常見的邏輯,Nest 內(nèi)置了:
@Post('fff')
@UseInterceptors(FileInterceptor('aaa', {
dest: 'uploads'
}))
uploadFile3(@UploadedFile(new ParseFilePipe({
validators: [
new MaxFileSizeValidator({ maxSize: 1000 }),
new FileTypeValidator({ fileType: 'image/jpeg' }),
],
})) file: Express.Multer.File, @Body() body) {
console.log('body', body);
console.log('file', file);
}
MaxFileSizeValidator 是校驗文件大小、FileTypeValidator 是校驗文件類型。

返回的也是 400 響應(yīng),并且 message 說明了具體的錯誤信息。
而且這個錯誤信息 message 可以通過 exceptionFactory 工廠函數(shù)自定義。
我們也可以自己實現(xiàn)這樣的 validator,只要繼承 FileValidator 就可以:
import { FileValidator } from '@nestjs/common';
export class MyFileValidator extends FileValidator {
constructor(options) {
super(options);
}
isValid(file: Express.Multer.File): boolean | Promise<boolean> {
if (file.size > 10000) {
return false;
}
return true;
}
buildErrorMessage(file: Express.Multer.File): string {
return `文件 ${file.originalname} 大小超出 10k`;
}
}
然后在 controller 用一下:

瀏覽器上傳文件:

可以看到我們自定義的 FileValidator 生效了。
最后注意限制文件大小,大小超過之后文件最終還是會上傳到服務(wù)器,因為文件寫入才能拿到相關(guān)信息,我們可以根據(jù)路徑來刪除不合規(guī)的文件。
以上就是Nest.js使用multer實現(xiàn)文件上傳功能的詳細(xì)內(nèi)容,更多關(guān)于Nest.js multer文件上傳的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Node.js中child_process實現(xiàn)多進(jìn)程
這篇文章主要介紹了Node.js中child_process實現(xiàn)多進(jìn)程,需要的朋友可以參考下2015-02-02
node.js中的http.response.writeHead方法使用說明
這篇文章主要介紹了node.js中的http.response.writeHead方法使用說明,本文介紹了http.response.writeHead的方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下2014-12-12
詳解NodeJS框架express的路徑映射(路由)功能及控制
這篇文章主要介紹了詳解NodeJS框架express的路徑映射(路由)功能及控制,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03
NodeJS實現(xiàn)微信公眾號關(guān)注后自動回復(fù)功能
這篇文章主要為大家詳細(xì)介紹了NodeJS實現(xiàn)微信公眾號關(guān)注后自動回復(fù)功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05
[將免費進(jìn)行到底]在Amazon的一年免費服務(wù)器上安裝Node.JS, NPM和OurJS博客
此文是介紹如何在Amazon的一年免費計劃上安裝Node.JS, NPM還有搭建OurJS博客系統(tǒng)。,需要的朋友可以參考下2014-08-08
nodejs連接ftp上傳下載實現(xiàn)方法詳解【附:踩坑記錄】
這篇文章主要介紹了nodejs連接ftp上傳下載實現(xiàn)方法,結(jié)合實例形式詳細(xì)分析了node.js使用ftp模塊實現(xiàn)針對ftp上傳、下載相關(guān)操作的方法,并附帶記錄了傳輸速度慢的解決方法,需要的朋友可以參考下2023-04-04
詳解基于Koa2開發(fā)微信二維碼掃碼支付相關(guān)流程
這篇文章主要介紹了詳解基于Koa2開發(fā)微信二維碼掃碼支付相關(guān)流程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05

