# nodejs-fileupload-sample **Repository Path**: fe521/nodejs-fileupload-sample ## Basic Information - **Project Name**: nodejs-fileupload-sample - **Description**: 大文件上传例子 nodejs express - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-06-25 - **Last Updated**: 2024-09-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 前后端大文件分片上传调研-express-fileupload 在线预览文档地址: https://docs.ffffee.com/project/file-upload/3-file-upload.html ## 一、如何获取代码 https://gitee.com/fe521/nodejs-fileupload-sample https://www.npmjs.com/package/express-fileupload ## 二、接口文档 服务器地址: 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); } } ); ```