前后端大文件分片上传调研-express-fileupload
一、如何获取代码
https://gitee.com/fe521/nodejs-fileupload-sample
二、接口文档
服务器地址: http://localhost:8001
1. 文件上传
请求 URL:
http://xx.com/api/upload
请求方式:
- POST
请求类型:
- multipart/form-data
参数:
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
sampleFile | 是 | file | 文件块 |
currentChunk | 是 | int | 当前文件块序号 |
totalChunks | 是 | int | 文件总块数 |
返回示例
json
{
"code": 200,
"message": "success",
"data": {
"uploaded": true
}
}
json
{
"code": 400,
"message": "No files were uploaded.",
"data": {
"uploaded": false
}
}
返回参数说明:
参数名 | 类型 | 说明 |
---|---|---|
code | int | 状态码 |
message | string | 返回信息 |
data | Object | 返回的数据 |
备注
- 更多返回错误代码请看首页的错误代码描述
- 文件分块上传,前端会将文件分割成多个块,每个块单独发送一个请求,服务器端需要支持处理多个请求并合并文件。
2. 文件块合并
请求 URL:
http://xx.com/api/merge
请求方式:
- POST
请求类型:
- application/json
参数:
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
fileName | 是 | string | 文件名 |
totalChunks | 是 | int | 文件总块数 |
返回示例
json
{
"code": 200,
"message": "success",
"data": {
"merged": true
}
}
返回参数说明:
参数名 | 类型 | 说明 |
---|---|---|
code | int | 状态码 |
message | string | 返回信息 |
data | Object | 返回的数据 |
备注
- 更多返回错误代码请看首页的错误代码描述
- 当所有文件块上传完成后,前端会调用此接口进行文件块的合并。
根据你提供的代码,以下是对应的三个后端接口的文档 Markdown 模板:
3. 获取文件列表
请求 URL:
http://xx.com/api/filelist
请求方式:
- GET
返回示例
json
{
"code": 200,
"type": "success",
"data": {
"totalFiles": 100,
"page": 1,
"limit": 10,
"files": ["file1", "file2", "file3"]
}
}
返回参数说明:
参数名 | 类型 | 说明 |
---|---|---|
code | int | 状态码 |
type | string | 响应类型,成功为 "success" |
data | Object | 返回的数据,包含一个文件名数组 |
data.totalFiles | Object | 返回的数据,包含一个文件名数组 |
data.page | int | 当前页 |
data.limit | int | 每一条数 |
data.files | Array | 文件名称列表 |
备注
- 更多返回错误代码请看首页的错误代码描述
4. 文件下载
请求 URL:
http://xx.com/api/download/{fileName}
请求方式:
- GET
URL 参数:
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
fileName | 是 | string | 文件名 |
返回:
- 文件的二进制流
备注
- 更多返回错误代码请看首页的错误代码描述
5. 删除文件
请求 URL:
http://xx.com/api/delete/{fileName}
请求方式:
- DELETE
URL 参数:
参数名 | 必选 | 类型 | 说明 |
---|---|---|---|
fileName | 是 | string | 文件名 |
返回示例
json
{
"code": 200,
"message": "success",
"data": {
"deleted": true
}
}
返回参数说明:
参数名 | 类型 | 说明 |
---|---|---|
code | int | 状态码 |
message | string | 返回信息 |
data | Object | 返回的数据 |
备注
- 更多返回错误代码请看首页的错误代码描述
三、实现步骤
1. 打开 express-fileupload 开源仓库地址
https://www.npmjs.com/package/express-fileupload
2. 进入到 GitHub 页面
https://github.com/richardgirges/express-fileupload#readme
3. 点击 Download 按钮 下载开源库
https://github.com/richardgirges/express-fileupload/archive/refs/heads/master.zip
4. 本地创建项目目录
bash
mkdir -p nodejs-fileupload-sample
5. 创建 package.json
bash
# node 版本,如果没有node,先安装node
node -v
v18.15.0
bash
npm init -y
6. 把下载 express-fileupload 的 zip 包解压,并拷贝 example 目录到当前项目的根目录
此时 nodejs-fileupload-sample/目录下应该有
server.js
index.html
7. 修改 server.js 中的内容
修改前
js
const express = require("express");
const fileUpload = require("../lib/index");
const app = express();
修改后
js
const express = require("express");
const fileUpload = require("express-fileupload");
const app = express();
8. 安装 express、express-fileupload 和 nodemon
bash
npm install express express-fileupload nodemon
9. 修改 package.json "scripts" 启动项目
json
"scripts": {
"start": "nodemon server.js"
},
10. 启动项目后端文件上传项目
bash
npm start
此时已经实现了文件上传功能,访问端口 http://localhost:8000/form 可以看到 index.html 内容
11. 初始化代码仓库并提交代码
bash
git init
bash
git add .
bash
git commit -m 'feat: '
12. 打开码云-创建一个仓库-名称为 nodejs-fileupload-sample
13. 拷贝 remote 命令 git@gitee.com:fe521 部分修改成你们自己的
注意:使用 ssh 的方式
bash
git remote add origin git@gitee.com:fe521/nodejs-fileupload-sample.git
检查是否添加成功,出现下面状态时成功的
powershell
PS D:\dev\file-upload-sample> git remote -v
origin git@gitee.com:fe521/nodejs-fileupload-sample.git (fetch)
origin git@gitee.com:fe521/nodejs-fileupload-sample.git (push)
14. 在本地提交代码
powershell
PS D:\dev\file-upload-sample> git push
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin main
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
拷贝命令,终端中输入
powershell
git push --set-upstream origin main
完成提交代码
15. 更多内容看视频
视频在 “李钟意讲前端” 抖音店铺课程 - “web 全栈”
四、常见问题
1. 上传文件-中文名称乱码
解决方案如下
js
app.use(
fileUpload({
// 解决中文乱码:https://www.jianshu.com/p/813d85daaf60
createParentPath: true,
defParamCharset: "utf8", // 添加utf8编码
limits: { fileSize: 5 * 1024 * 1024 }, // 5M (上传大于次大小会自动截取掉)
useTempFiles: true, // 使用临时模板目录
tempFileDir: path.resolve(__dirname, "./uploads-tmp/"),
})
);
2. (node:18784) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 finish listeners added to [WriteStream]. Use emitter.setMaxListeners()
遇到这个问题,通过 async 模块 实现并发限制
bash
npm i async
js
async.eachLimit(
chunkIndices,
8,
function (chunkIndex, done) {
const readStream = fs.createReadStream(`${uploadPath}_temp_${chunkIndex}`);
readStream.pipe(writeStream, { end: false });
readStream.on("end", function () {
mergedChunks++;
if (mergedChunks === totalChunks) {
writeStream.end();
}
done();
});
readStream.on("error", function (err) {
writeStream.end();
callback(err);
});
},
function (err) {
if (err) {
console.error("Error", err);
callback(err);
} else {
callback(err);
}
}
);