Reactjs + Nodejs + Express + Mongodb 搭建[图片上传/预览]前后端项目
概述
图片上传功能,在日常的项目开发中是很常见的功能,今天我们就来说说使用 Reactjs + Nodejs + Express + Mongodb
搭建前后端图片上传的例子
我们先看看完成后的效果
跟随本示例学习,你也可以搭建出来。
后端部分
实现的功能:
图片上传功能
图片上传显示进度条功能
图片预览功能
图片列表功能
图片下载功能
后端使用的技术/数据库:
Nodejs
Express
Multer
Mongodb
Multer-gridfs-storage
Cors
后端部分我们使用 Nodejs + Express + Multer + Mongodb
来搭建图片上传的项目,配合前端 Reactjs + Axios
来共同实现图片上传的前后端项目。
后端项目目录结构
├── README.md├── node_modules├── package-lock.json├── package.json└── src ├── config │ └── db.js ├── controllers │ ├── home.js │ └── upload.js ├── middleware │ └── upload.js ├── routes │ └── index.js ├── server.js └── views └── index.html
config/db.js:包括 MongoDB
和 Multer
的配置(url、数据库、图像存储桶)。
routes/index.js:定义从视图调用的端点的路由,使用控制器来处理请求。
controllers: home.js返回 views/index.html
upload.js处理上传、存储、显示和下载图像
middleware/upload.js:初始化 Multer GridFs
存储引擎(包括 MongoDB
)并定义中间件函数。
server.js:初始化路由,配置 CORS,入口文件
后端项目我们提供以下几个API
文件上传接口
文件列表获取接口
使用 url
下载文件接口
我们可以使用 postman
工具先看下接口的情况,如下图
文件上传接口
获取文件列表接口
打开数据库连接工具,可以看到,数据库里,已经有上传的文件了
创建项目 配置模块
我们先使用命令 mkdir
创建一个空文件夹,然后 cd
到文件夹里面
这个文件夹就是我们的项目文件夹
mkdir nodejs-express-upload-filescd nodejs-express-upload-files
接着使用命令
npm init
初始化项目,接着安装项目需要的依赖包, 输入如下命令
npm install express cors multer multer-gridfs-storage mongodb
package.js 文件
{ "name": "nodejs-express-upload-files", "version": "1.0.0", "description": "Node.js upload multiple files/images to MongoDB", "main": "src/server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "node", "upload", "multiple", "files", "images", "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" }}
配置 MongoDB 数据库
config/db.js
module.exports = { url: "mongodb://localhost:27017/", database: "files_db", imgBucket: "photos",};
配置图片上传存储的中间件
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"]; if (match.indexOf(file.mimetype) === -1) { const filename = file.originalname; return filename; } return { bucketName: dbConfig.imgBucket, filename: file.originalname }; }});var uploadFiles = multer({ storage: storage }).array("file", 10);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.mimetype。bucketName表示文件将存储在photos.chunks和photos.files集合中。
接下来我们使用multer模块来初始化中间件util.promisify()并使导出的中间件对象可以与async-await.
single()带参数的函数是input标签的名称
创建文件上传的控制器
controllers/upload.js
这个文件主要用于图片上传,我们创建一个名 upload
函数,并将这个函数导出去
我们使用 文件上传中间件函数处理上传的文件
使用 Multer
捕获相关错误
返回响应
文件列表数据获取和下载
getListFiles
函数主要是获取 photos.files
,返回 url, name, id
download()
: 接收文件 id
作为输入参数,从 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); console.log(req.files); if (req.files.length <= 0) { return res .status(400) .send({ message: "You must select at least 1 file." }); } return res.status(200).send({ message: "文件上传成功", }); // console.log(req.file); // if (req.file == undefined) { // return res.send({ // message: "You must select a file.", // }); // } // return res.send({ // message: "File has been uploaded.", // }); } catch (error) { console.log(error); if (error.code === "LIMIT_UNEXPECTED_FILE") { return res.status(400).send({ message: "Too many files to upload.", }); } return res.status(500).send({ message: `Error when trying upload many files: ${error}`, }); // return res.send({ // message: "Error when trying upload image: ${error}", // }); }};const getListFiles = async (req, res) => { try { await mongoClient.connect(); const database = mongoClient.db(dbConfig.database); const images = database.collection(dbConfig.imgBucket + ".files"); let fileInfos = []; if ((await images.estimatedDocumentCount()) === 0) { fileInfos = [] } let cursor = images.find({}) await cursor.forEach((doc) => { fileInfos.push({ id: doc._id, 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.imgBucket, }); 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: "Cannot download the Image!" }); }); downloadStream.on("end", () => { return res.end(); }); } catch (error) { return res.status(500).send({ message: error.message, }); }};module.exports = { uploadFiles, getListFiles, download,};
定义路由
在 routes
文件夹中,使用 Express Router
在 index.js
中定义路由
const express = require("express");const router = express.Router();const homeController = require("../controllers/home");const uploadController = require("../controllers/upload");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
控制器的功能。
获取/files图像列表。
GET/files/:name下载带有文件名的图像。
创建 Express
服务器
server.js
const cors = require("cors");const express = require("express");const app = express();const initRoutes = require("./routes");var corsOptions = { origin: "http://localhost:8081"};app.use(cors(corsOptions));app.use(express.urlencoded({ extended: true }));initRoutes(app);let port = 8080;app.listen(port, () => { console.log(`Running at localhost:${port}`);});
这里我们导入了 express
和 cors
,
Express
用于构建 Rest api
Cors
提供 Express
中间件以启用具有各种选项的 CORS
。
创建一个 Express
应用程序,然后使用方法添加 Cors
中间件 在端口 8080
上侦听传入请求。
运行项目并测试
在项目根目录下在终端中输入命令 node src/server.js
, 控制台显示
Running at localhost:8080
使用 postman
工具测试,ok 项目正常运行
文件上传接口
获取文件列表接口
打开数据库连接工具,可以看到,数据库里,已经有上传的文件了
联调
我们先启动后端项目 node src/server.js
, 接着再启动前端项目 npm start
,
测试上传,获取等接口,一切正常。
到这里整个前后端「上传图片」功能示例就算完成了。
原文:https://juejin.cn/post/7103518888100364302