基于Express+multer實(shí)現(xiàn)文件上傳功能
1.涉及依賴包
- multer: 處理文件上傳的
- cors: 處理跨域的
2.http-server
一個(gè)簡(jiǎn)單的http服務(wù)器,經(jīng)常用于本地測(cè)試和開發(fā)
安裝
// 全局安裝 sudo npm install http-server -g
使用
// 在當(dāng)前目錄下建立http服務(wù)器,啟動(dòng)后可以直接打開輸出內(nèi)容里的ip地址 http-server . // 指定ip和端口號(hào)http-server [path] [options] http-server -a 127.0.0.1 -p 9090

啟動(dòng)后即可根據(jù)所啟動(dòng)服務(wù)器的地址來(lái)訪問該服務(wù)下的資源,默認(rèn)訪問inex.html文件


3. 單文件上傳
安裝依賴
npm install express multer cors
npm install express multer cors
const express = require('express');
const multer = require('multer');
const cors = require('cors');
const app = express();
app.use(cors());
const upload = multer({ dest: 'files' });
app.post(
'/upload',
upload.single('aaa'),
function (req, res, next) {
console.log(req.file, 'file');
console.log(req.body, 'body');
},
function (err, req, res, next) {}
);
app.listen(3333);
app.use是使用cors中間件來(lái)處理跨域。
multer處理文件上傳,指定保存文件的目錄是files。
因?yàn)閙ulter本身是一個(gè)函數(shù),所以不需要app.use。
upload.single是在處理單文件的時(shí)候使用single。
upload.single('aaa')是指接文件的參數(shù)名是aaa。
創(chuàng)建一個(gè)index.html文件來(lái)作為文件入口
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
<input id="fileInput" type="file" />
<script>
const fileInput = document.querySelector('#fileInput');
async function formData() {
const data = new FormData();
data.set('name', 'yangmy');
data.set('age', 20);
data.set('file', fileInput.files[0]);
const res = await axios.post('http://localhost:3333/upload', data);
}
fileInput.onchange = formData;
</script>
</body>
</html>
然后使用http-server在當(dāng)前目錄下啟動(dòng)一個(gè)http服務(wù):

在當(dāng)前目錄下運(yùn)行index.js文件:
node index.js
在瀏覽器中打開http-server創(chuàng)建的服務(wù)地址,此時(shí)后默認(rèn)打開index.html文件:

選一張圖片上傳:

此時(shí)可以看到瀏覽器的請(qǐng)求參數(shù)以及服務(wù)端打印的日志:
瀏覽器:

服務(wù)端:

然后就可以看到我們代碼中就會(huì)多出一個(gè)files的文件夾,里面存放的是剛上傳的問件:

4.多文件上傳
在index.js中添加一個(gè)新的路由,用于處理多文件上傳:
const express = require('express');
const multer = require('multer');
const cors = require('cors');
const app = express();
app.use(cors());
const upload = multer({ dest: 'files' });
app.post(
'/upload',
upload.single('file'),
function (req, res, next) {
console.log(req.file, 'file');
console.log(req.body, 'body');
},
function (err, req, res, next) {}
);
app.post(
'/uploads',
upload.array('filelist', 2),
function (req, res, next) {
console.log(req.files, 'file');
console.log(req.body, 'body');
},
function (err, req, res, next) {}
);
app.listen(3333);
這里修改了index.js文件,添加了/uploads接口,用作處理多文件上傳。相比于單文件上傳,修改了以下:

upload.single('file')改成了upload.array('filelist', 2),因?yàn)橐蟼鞫辔募?,所?code>single變成了array,第二個(gè)數(shù)字參數(shù)是文件上傳的數(shù)量限制。
新建一個(gè)multis.html用來(lái)當(dāng)作多文件上傳的頁(yè)面,頁(yè)面內(nèi)容是:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
as
<input id="fileInput" type="file" multiple />
<script>
const fileInput = document.querySelector('#fileInput');
async function formData2() {
const data = new FormData();
data.set('name', 'yangmy');
data.set('age', 20);
[...fileInput.files].forEach((item) => {
data.append('filelist', item);
});
const res = await axios.post('http://localhost:3333/uploads', data);
console.log(res);
}
fileInput.onchange = formData2;
</script>
</body>
</html>
重新運(yùn)行項(xiàng)目:node index.js:
打開服務(wù)頁(yè)面,路由中輸入multis.html路由,然后上傳兩個(gè)圖片文件:

此時(shí)訪問的是多文件上傳頁(yè)面,接口參數(shù)中的filelist包含兩個(gè)文件參數(shù),再看控制臺(tái)打印的日志:

如圖:req.files打印出兩個(gè)文件的數(shù)據(jù)
如果我們上傳超過2個(gè)文件的數(shù)據(jù)呢?上傳超過規(guī)定的文件數(shù)量后,文件上傳會(huì)失敗,并不會(huì)上傳到我們的files文件夾中。
在多文件上傳的接口代碼中加入一個(gè)錯(cuò)誤處理的中間件:

此時(shí)可以在接口函數(shù)的第四個(gè)參數(shù)中拿到錯(cuò)誤信息,把錯(cuò)誤信息打印一下,展示如下:

我們可以通過這個(gè)報(bào)錯(cuò)的code來(lái)處理返回結(jié)果,在index.js的多文件上傳接口后加上如下代碼:

這樣再次試試上傳多個(gè)文件的情況:

此時(shí)便會(huì)根據(jù)錯(cuò)誤處理的邏輯,當(dāng)上傳文件數(shù)量過多時(shí)接口會(huì)400,且返回to many file的提示
5.多個(gè)字段上傳文件且限制不同
在index.js文件中添加一個(gè)新的接口uploadFileds,作為上傳多個(gè)字段,且限制不同的接口,代碼如下:
app.post(
'/uploadFileds',
upload.fields([
{ name: 'files1', maxCount: 2 },
{ name: 'files2', maxCount: 3 },
]),
function (req, res, next) {
console.log(req.files, 'file');
console.log(req.body, 'body');
},
function (err, req, res, next) {
console.log(err, 'err');
if (err.code === 'LIMIT_UNEXPECTED_FILE') {
res.status(400).end('to many files');
}
}
);
其中upload.fields指定了每個(gè)字段的字段名以及該字段名接收文件的限制,然后接收到請(qǐng)求后同樣使用req.files來(lái)獲取文件信息。
然后新建multisFileds.html文件,作為這個(gè)測(cè)試的頁(yè)面,代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<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 formData2() {
const data = new FormData();
data.set('name', 'yangmy');
data.set('age', 20);
data.append('files1', fileInput.files[0]);
data.append('files1', fileInput.files[1]);
data.append('files2', fileInput.files[2]);
data.append('files2', fileInput.files[3]);
data.append('files2', fileInput.files[4]);
const res = await axios.post(
'http://localhost:3333/uploadFileds',
data
);
console.log(res);
}
fileInput.onchange = formData2;
</script>
</body>
</html>
其中上傳的字段名和接口中定義的都必須對(duì)應(yīng)才可以。
訪問multisFileds.html頁(yè)面,并上傳五張圖片文件

上傳成功后我們看到存放文件夾的文件確實(shí)多了五條數(shù)據(jù),且,控制臺(tái)也打印出這些文件的信息

6.不確定上傳文件的字段
不確定上傳文件的字段以及限制時(shí),使用upload.any()來(lái)接收文件。
再次在index.js中新增一個(gè)接口:
app.post(
'/uploadfileNoname',
upload.any(),
function (req, res, next) {
console.log(req.files, 'file');
console.log(req.body, 'body');
},
function (err, req, res, next) {
console.log(err, 'err');
if (err.code === 'LIMIT_UNEXPECTED_FILE') {
res.status(400).end('to many files');
}
}
);
復(fù)用multisFileds.html文件,將上傳的接口改為uploadfileNoname

重新運(yùn)行express應(yīng)用,然后在瀏覽器中打開multisFileds.html頁(yè)面,選中文件上傳

上傳成功后看到files文件夾下面又多了5條文件數(shù)據(jù)

這時(shí)控制臺(tái)日志打印的文件內(nèi)容包含有所上傳的文件信息,但是這次沒有字段名,字段名都在文件信息中,需要一個(gè)個(gè)去遍歷處理

7.保存上傳的文件名
const upload = multer({ dest: 'files' });
之前通過dest指定了保存文件的路徑是files文件夾,現(xiàn)在修改一下,通過multer.diskStorage()方法來(lái)配置filename、destination參數(shù),使其將文件保存在指定的文件夾,且指定文件名和文件名后綴 在index.js中添加如下代碼:
const fs = require('fs');
const path = require('path');
const storage = multer.diskStorage({
// 目錄
destination: (req, file, cb) => {
try {
fs.mkdirSync(path.join(process.cwd(), 'uploadFile'));
} catch (e) {}
cb(null, path.join(process.cwd(), 'uploadFile'));
},
// 文件名
filename: (req, file, cb) => {
cb(null, file.originalname);
},
});
const upload = multer({ storage });
要注意destination和filename中的回調(diào)函數(shù)cb的第一個(gè)參數(shù)是傳的錯(cuò)誤信息,所以這里要注意傳null。
生成的storage要放到const upload = multer({ storage });中,這樣上傳時(shí)就會(huì)走寫的那個(gè)方法了。
然后我們?cè)谏弦粋€(gè)例子中使用上傳功能,成功上傳圖片后,發(fā)現(xiàn)上傳的圖片出現(xiàn)在了定義的uploadFile文件夾下,且名字我們使用的是上傳文件原本的名稱

以上就是基于Express+multer來(lái)實(shí)現(xiàn)文件上傳功能的詳細(xì)內(nèi)容,更多關(guān)于Express multer文件上傳功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Node綁定全局TraceID的實(shí)現(xiàn)方法
這篇文章主要介紹了Node 綁定全局 TraceID的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
基于node實(shí)現(xiàn)websocket協(xié)議
這篇文章主要介紹了基于node實(shí)現(xiàn)websocket協(xié)議的相關(guān)資料,需要的朋友可以參考下2016-04-04
Node.js 使用流實(shí)現(xiàn)讀寫同步邊讀邊寫功能
本文通過代碼給大家介紹了Node.js 使用流實(shí)現(xiàn)讀寫同步邊讀邊寫功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的額朋友參考下吧2017-09-09
淺談如何通過node.js對(duì)數(shù)據(jù)進(jìn)行MD5加密
本篇文章將主要針對(duì)于在NODE.JS中如何對(duì)數(shù)據(jù)進(jìn)行MD5加密,MD5是一種常用的哈希算法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-05-05
express搭建的nodejs項(xiàng)目使用webpack進(jìn)行壓縮打包
對(duì)于打包這個(gè)問題它并不是難點(diǎn),但是對(duì)于我們這種初學(xué)者來(lái)說(shuō),根本就不知道應(yīng)該怎么做,下面這篇文章主要給大家介紹了關(guān)于express搭建的nodejs項(xiàng)目使用webpack進(jìn)行壓縮打包的相關(guān)資料,需要的朋友可以參考下2022-12-12
npm?install總是卡住不動(dòng)問題的解決辦法
在我們安裝完Node.js之后,需要使用npm命令來(lái)安裝一些工具,下面這篇文章主要給大家介紹了關(guān)于npm?install總是卡住不動(dòng)問題的解決辦法,需要的朋友可以參考下2022-05-05
提升node.js中使用redis的性能遇到的問題及解決方法
本文中提到的node redis client采用的基于node-redis封裝的二方包,因此問題排查也基于node-redis這個(gè)模塊。接下來(lái)通過本文給大家分享提升node.js中使用redis的性能2018-10-10

