1
头图

本文完整版:《后端实战手把手教你写文件上传接口:如何使用 Node.js + MongoDB 开发 RESTful API 接口(Node.js + Express + MongoDB)

本教程手把手教你搭建一套后端文件上传 API 接口,它使用 Node.js + Express + MongoDB 构建的后端服务。本文详细描述通过 Node.js 与数据库通讯。整个服务搭建起来后,我们使用 Postman 对整个后端服务进行测试。

本教程每段代码我都亲手测过,保证百分百没有错误,请打开你的 terminal 跟随本教程一起操作,从这里开始,成为一名后端工程师。

全栈实战教程:

后端实战教程:

如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可快速搭建属于你自己的后台管理工具,一周工作量缩减至一天,详见本文文末。

✦ 文件上传管理后台 Node.js + Express + Multer + MongoDB

Node.js + Express + Multer + MongoDB

我们使用 Nodejs + Express + Multer + Mongodb 来搭建后端文件上传 API 后台接口。

后端项目我们提供以下几个API

  • POST /upload 文件上传接口
  • GET /files 文件列表获取接口
  • GET /files/[filename] 下载指定文件

后端项目结构

├── README.md
├── package.json
├── pnpm-lock.yaml
└── node_modules
    └── ...
└── src
    ├── config
    │   └── db.js
    ├── controllers
    │   └── flileUploadController.js
    ├── middleware
    │   └── upload.js
    ├── routes
    │   └── index.js
    └── server.js
  • src/db.js 包括 MongoDB 和 Multer 的配置(url、数据库、文件存储桶)。
  • middleware/upload.js:初始化 Multer GridFs 存储引擎(包括 MongoDB)并定义中间件函数。
  • controllers/flileUploadController.js:配置 Rest API
  • routes/index.js:路由,定义前端请求后端如何执行
  • server.js:Node.js入口文件

扩展阅读:《React Echarts 使用教程 - 如何在 React 中加入图表

配置 Node.js 开发环境

我们先使用命令 mkdir 创建一个空文件夹,然后 cd 到文件夹里面 这个文件夹就是我们的项目文件夹

mkdir kalacloud-nodejs-mongodb-upload-files
cd kalacloud-nodejs-mongodb-upload-files

接着使用命令

初始化项目,接着安装项目需要的依赖包, 输入如下命令

npm install express cors multer multer-gridfs-storage mongodb

package.js 文件

{
  "name": "kalacloud-nodejs-mongodb-upload-files",
  "version": "1.0.0",
  "description": "Node.js upload multiple files to MongoDB",
  "main": "src/server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "node",
    "upload",
    "multiple",
    "files",
    "mongodb"
  ],
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "mongodb": "^4.1.3",
    "multer": "^1.4.3",
    "multer-gridfs-storage": "^5.0.2"
  }
}

扩展阅读:《React Router 6 (React路由) 最详细教程

配置 MongoDB 数据库

src/config/db.js

module.exports = {
  url: "mongodb://localhost:27017/",
  database: "files_db",
  filesBucket: "photos",
};

配置文件上传存储的中间件

src/middleware/upload.js

const util = require("util");
const multer = require("multer");
const { GridFsStorage } = require("multer-gridfs-storage");
const dbConfig = require("../config/db");

var storage = new GridFsStorage({
  url: dbConfig.url + dbConfig.database,
  options: { useNewUrlParser: true, useUnifiedTopology: true },
  file: (req, file) => {
    const match = ["image/png", "image/jpeg", "image/gif"];

    if (match.indexOf(file.mimetype) === -1) {
      const filename = `${Date.now()}-kalacloud-${file.originalname}`;
      return filename;
    }
    return {
      bucketName: dbConfig.filesBucket,
      filename: `${Date.now()}-kalacloud-${file.originalname}`
    };
  }
});
const maxSize = 2 * 1024 * 1024;
var uploadFiles = multer({ storage: storage, limits: { fileSize: maxSize } }).single("file");
var uploadFilesMiddleware = util.promisify(uploadFiles);
module.exports = uploadFilesMiddleware;

这里我们定义一个 storage 的配置对象 GridFsStorage

  • url: 必须是指向 MongoDB 数据库的标准 MongoDB 连接字符串。multer-gridfs-storage 模块将自动为您创建一个 mongodb 连接。
  • options: 自定义如何建立连接
  • file: 这是控制数据库中文件存储的功能。该函数的返回值是一个具有以下属性的对象:filename, metadata, chunkSize, bucketName, contentType... 我们还检查文件是否为图像 file.mimetypebucketName 表示文件将存储在 photos.chunksphotos.files 集合中。
  • 接下来我们使用 multer 模块来初始化中间件 util.promisify() 并使导出的中间件对象可以与 async-await.
  • single() 带参数的函数是 input 标签的名称
  • 这里使用 Multer API 来限制上传文件大小,添加 limits: { fileSize: maxSize } 以限制文件大小

扩展阅读:《最好的 6 个 React Table 组件详细亲测推荐

创建文件上传的控制器

controllers/flileUploadController.js

这个文件主要用于文件上传,我们创建一个名 upload 函数,并将这个函数导出去

  • 我们使用 文件上传中间件函数处理上传的文件
  • 使用 Multer 捕获相关错误
  • 返回响应

文件列表数据获取和下载

  • getListFiles: 函数主要是获取 photos.files,返回 url, name
  • download(): 接收文件 name 作为输入参数,从 mongodb 内置打开下载流 GridFSBucket,然后 response.write(chunk) API 将文件传输到客户端。
const upload = require("../middleware/upload");
const dbConfig = require("../config/db");

const MongoClient = require("mongodb").MongoClient;
const GridFSBucket = require("mongodb").GridFSBucket;

const url = dbConfig.url; 

const baseUrl = "http://localhost:8080/files/";

const mongoClient = new MongoClient(url);

const uploadFiles = async (req, res) => {
  try {
    await upload(req, res);
    if (req.file == undefined)  {
      return res.status(400).send({ message: "请选择要上传的文件" });
    }
    return res.status(200).send({
      message: "文件上传成功" + req.file.originalname,
    });
  } catch (error) {
    console.log(error);
     if (error.code == "LIMIT_FILE_SIZE") {
      return res.status(500).send({
        message: "文件大小不能超过 2MB",
      });
    }
    return res.status(500).send({
      message: `无法上传文件:, ${error}`
    });
  }
};

const getListFiles = async (req, res) => {
  try {
    await mongoClient.connect();

    const database = mongoClient.db(dbConfig.database); 
    const files = database.collection(dbConfig.filesBucket + ".files");
    let fileInfos = [];

    if ((await files.estimatedDocumentCount()) === 0) {
        fileInfos = []
    }

    let cursor = files.find({})
    await cursor.forEach((doc) => {
      fileInfos.push({
        name: doc.filename,
        url: baseUrl + doc.filename,
      });
    });

    return res.status(200).send(fileInfos);
  } catch (error) {
    return res.status(500).send({
      message: error.message,
    });
  }
};

const download = async (req, res) => {
  try {
    await mongoClient.connect();
    const database = mongoClient.db(dbConfig.database);
    const bucket = new GridFSBucket(database, {
      bucketName: dbConfig.filesBucket,
    });

    let downloadStream = bucket.openDownloadStreamByName(req.params.name);
    downloadStream.on("data", function (data) {
      return res.status(200).write(data);
    });

    downloadStream.on("error", function (err) {
      return res.status(404).send({ message: "无法获取文件" });
    });

    downloadStream.on("end", () => {
      return res.end();
    });
  } catch (error) {
    return res.status(500).send({
      message: error.message,
    });
  }
};

module.exports = {
  uploadFiles,
  getListFiles,
  download,
};

扩展阅读:《React Draggable 实现拖拽 - 最详细中文教程

定义 routes 路由

routes 文件夹中,使用 Express Routerindex.js 中定义路由

const express = require("express");
const router = express.Router();
const uploadController = require("../controllers/flileUploadController");

let routes = app => {
  router.post("/upload", uploadController.uploadFiles);
  router.get("/files", uploadController.getListFiles);
  router.get("/files/:name", uploadController.download);
  return app.use("/", router);
};
 
module.exports = routes;
  • POST /upload: 调用 uploadFiles控制器的功能。
  • GET /files 获取/files图像列表。
  • GET /files/:name 下载带有文件名的图像。

创建 Express 服务器

const cors = require("cors");
const express = require("express");
const app = express();
global.__basedir = __dirname;
var corsOptions = {
  origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
const initRoutes = require("./routes");
app.use(express.urlencoded({ extended: true }));
initRoutes(app);
let port = 8080;
app.listen(port, () => {
  console.log(`Running at localhost:${port}`);
});

这里我们导入了 ExpressCors,

  • Express 用于构建 Rest api
  • Cors提供 Express 中间件以启用具有各种选项的 CORS。 创建一个 Express 应用程序,然后使用方法添加cors中间件 在端口 8080 上侦听传入请求。

运行项目并测试

在项目根目录下在终端中输入命令 node src/server.js, 控制台显示

Running at localhost:8080

使用 postman 工具测试,ok 项目正常运行

文件上传接口

postman文件上传接口

文件列表接口

postman文件列表接口

MongoDB 数据库

postman数据库

到这里整个后端「上传文件」管理后台就搭建完成了。

Node.js 后端「文件上传」源码 你可以在我们的 github 上下载到完整的 Node.js 后端「文件上传」源码。

如果你还没搞懂,也不用着急,直接使用卡拉云,无需懂任何前后端技术,仅需简单的鼠标拖拽即可快速生成包括「文件上传」管理在内的任何后台管理工具。

「文件上传」前后端搭建总结及卡拉云

本教程手把手教大家搭建 React 前端 + Node.js 后端 的「文件上传」管理工具,如果你一步步跟着走,一定已经把 Demo 跑起来了。但如果你会使用最新的低代码开发工具「卡拉云」,完全不需要这么繁琐,仅需 1 分钟,就能搭建起属于自己的「文件上传」管理工具。

卡拉云文件上传管理

立即开通卡拉云,从侧边工具栏直接拖拽组件到页面,生成上传组件和文件管理工具。1 分钟搞定「上传文件」管理工具。

再看个卡拉云的 Demo 案例,下面是用卡拉云搭建的数据库 CURD 后台管理系统,只需拖拽组件,即可在10分钟内完成搭建。

可直接分享给同事一起使用:https://my.kalacloud.com/apps/8z9z3yf9fy/published

卡拉云可帮你快速搭建企业内部工具,下图为使用卡拉云搭建的内部广告投放监测系统,无需懂前端,仅需拖拽组件,10 分钟搞定。你也可以快速搭建一套属于你的后台管理工具。

卡拉云企业内部工具

卡拉云是新一代低代码开发平台,与前端框架 Vue、React等相比,卡拉云的优势在于不用首先搭建开发环境,直接注册即可开始使用。开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。立即免费试用卡拉云

全栈实战教程:

后端实战教程:


蒋川
158 声望14 粉丝