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

啟動后即可根據(jù)所啟動服務(wù)器的地址來訪問該服務(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中間件來處理跨域。
multer處理文件上傳,指定保存文件的目錄是files。
因為multer本身是一個函數(shù),所以不需要app.use。
upload.single是在處理單文件的時候使用single。
upload.single('aaa')是指接文件的參數(shù)名是aaa。
創(chuàng)建一個index.html文件來作為文件入口
<!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)前目錄下啟動一個http服務(wù):

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

選一張圖片上傳:

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

服務(wù)端:

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

4.多文件上傳
在index.js中添加一個新的路由,用于處理多文件上傳:
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),因為要上傳多文件,所以single變成了array,第二個數(shù)字參數(shù)是文件上傳的數(shù)量限制。
新建一個multis.html用來當(dāng)作多文件上傳的頁面,頁面內(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>
重新運行項目:node index.js:
打開服務(wù)頁面,路由中輸入multis.html路由,然后上傳兩個圖片文件:

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

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

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

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

這樣再次試試上傳多個文件的情況:

此時便會根據(jù)錯誤處理的邏輯,當(dāng)上傳文件數(shù)量過多時接口會400,且返回to many file的提示
5.多個字段上傳文件且限制不同
在index.js文件中添加一個新的接口uploadFileds,作為上傳多個字段,且限制不同的接口,代碼如下:
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指定了每個字段的字段名以及該字段名接收文件的限制,然后接收到請求后同樣使用req.files來獲取文件信息。
然后新建multisFileds.html文件,作為這個測試的頁面,代碼如下:
<!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>
其中上傳的字段名和接口中定義的都必須對應(yīng)才可以。
訪問multisFileds.html頁面,并上傳五張圖片文件

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

6.不確定上傳文件的字段
不確定上傳文件的字段以及限制時,使用upload.any()來接收文件。
再次在index.js中新增一個接口:
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

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

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

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

7.保存上傳的文件名
const upload = multer({ dest: 'files' });
之前通過dest指定了保存文件的路徑是files文件夾,現(xiàn)在修改一下,通過multer.diskStorage()方法來配置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的第一個參數(shù)是傳的錯誤信息,所以這里要注意傳null。
生成的storage要放到const upload = multer({ storage });中,這樣上傳時就會走寫的那個方法了。
然后我們在上一個例子中使用上傳功能,成功上傳圖片后,發(fā)現(xiàn)上傳的圖片出現(xiàn)在了定義的uploadFile文件夾下,且名字我們使用的是上傳文件原本的名稱

以上就是基于Express+multer來實現(xiàn)文件上傳功能的詳細(xì)內(nèi)容,更多關(guān)于Express multer文件上傳功能的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于node實現(xiàn)websocket協(xié)議
這篇文章主要介紹了基于node實現(xiàn)websocket協(xié)議的相關(guān)資料,需要的朋友可以參考下2016-04-04
淺談如何通過node.js對數(shù)據(jù)進行MD5加密
本篇文章將主要針對于在NODE.JS中如何對數(shù)據(jù)進行MD5加密,MD5是一種常用的哈希算法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
express搭建的nodejs項目使用webpack進行壓縮打包
對于打包這個問題它并不是難點,但是對于我們這種初學(xué)者來說,根本就不知道應(yīng)該怎么做,下面這篇文章主要給大家介紹了關(guān)于express搭建的nodejs項目使用webpack進行壓縮打包的相關(guān)資料,需要的朋友可以參考下2022-12-12
提升node.js中使用redis的性能遇到的問題及解決方法
本文中提到的node redis client采用的基于node-redis封裝的二方包,因此問題排查也基于node-redis這個模塊。接下來通過本文給大家分享提升node.js中使用redis的性能2018-10-10

