node.js - 将 gridfs 与 node rest API 一起使用
问题描述
我正在尝试将 gridFs 存储与 node rest api 一起使用。我对如何将这两者结合使用感到困惑。我正在关注 Brad Traversy 的 gridfs 源代码。我应该在节点 rest 的“app.js”文件还是“product.js(Route 的文件夹)”中使用这些代码。
这是gridfs代码:
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const crypto = require('crypto');
const mongoose = require('mongoose');
const multer = require('multer');
const GridFsStorage = require('multer-gridfs-storage');
const Grid = require('gridfs-stream');
const methodOverride = require('method-override');
const app = express();
const productRoutes = require("./api/routes/products");
const userRoutes = require("./api/routes/user");
app.use(morgan("dev"));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method === "OPTIONS") {
res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
return res.status(200).json({});
}
next();
});
// Routes which should handle requests
app.use("/products", productRoutes);
app.use("/user", userRoutes);
app.use((req, res, next) => {
const error = new Error("Not found");
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
module.exports = app;
// Middleware
app.use(bodyParser.json());
app.use(methodOverride('_method'));
app.set('view engine', 'ejs');
// Mongo URI
const mongoURI = 'mongodb://brad:brad@ds257838.mlab.com:57838/mongouploads';
// Create mongo connection
const conn = mongoose.createConnection(mongoURI);
// Init gfs
let gfs;
conn.once('open', () => {
// Init stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('uploads');
});
// Create storage engine
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: 'uploads'
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
// @route GET /
// @desc Loads form
app.get('/', (req, res) => {
gfs.files.find().toArray((err, files) => {
// Check if files
if (!files || files.length === 0) {
res.render('index', { files: false });
} else {
files.map(file => {
if (
file.contentType === 'image/jpeg' ||
file.contentType === 'image/png'
) {
file.isImage = true;
} else {
file.isImage = false;
}
});
res.render('index', { files: files });
}
});
});
// @route POST /upload
// @desc Uploads file to DB
app.post('/upload', upload.single('file'), (req, res) => {
// res.json({ file: req.file });
res.redirect('/');
});
// @route GET /files
// @desc Display all files in JSON
app.get('/files', (req, res) => {
gfs.files.find().toArray((err, files) => {
// Check if files
if (!files || files.length === 0) {
return res.status(404).json({
err: 'No files exist'
});
}
// Files exist
return res.json(files);
});
});
// @route GET /files/:filename
// @desc Display single file object
app.get('/files/:filename', (req, res) => {
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
// Check if file
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// File exists
return res.json(file);
});
});
// @route GET /image/:filename
// @desc Display Image
app.get('/image/:filename', (req, res) => {
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
// Check if file
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// Check if image
if (file.contentType === 'image/jpeg' || file.contentType === 'image/png') {
// Read output to browser
const readstream = gfs.createReadStream(file.filename);
readstream.pipe(res);
} else {
res.status(404).json({
err: 'Not an image'
});
}
});
});
// @route DELETE /files/:id
// @desc Delete file
app.delete('/files/:id', (req, res) => {
gfs.remove({ _id: req.params.id, root: 'uploads' }, (err, gridStore) => {
if (err) {
return res.status(404).json({ err: err });
}
res.redirect('/');
});
});
这是我想在其中使用网格 fs 进行文件存储的路由文件夹中的 product.js 代码:
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, Date.now() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
const Product = require("../models/product");
router.get("/", (req, res, next) => {
Product.find()
.select("name price _id productImage reference description quantity date category")
.exec()
.then(docs => {
const response = {
count: docs.length,
products: docs.map(doc => {
return {
name: doc.name,
price: doc.price,
productImage: doc.productImage,
reference: doc.reference,
description: doc.description,
quantity: doc.quantity,
date: doc.date,
category: doc.category,
_id: doc._id,
request: {
type: "GET",
url: "https://booksbackend.herokuapp.com/products/" + doc._id
}
};
})
};
// if (docs.length >= 0) {
res.status(200).json(response);
// } else {
// res.status(404).json({
// message: 'No entries found'
// });
// }
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
router.post("/", upload.single('productImage'), (req, res, next) => {
const product = new Product({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
price: req.body.price,
productImage: req.file.filename,
reference: req.body.reference,
description: req.body.description,
quantity: req.body.quantity,
date: req.body.date,
category: req.body.category,
newProduct: req.body.newProduct,
relatedProduct: req.body.relatedProduct
});
product
.save()
.then(result => {
console.log(result);
res.status(201).json({
message: "Created product successfully",
createdProduct: {
name: result.name,
price: result.price,
_id: result._id,
request: {
type: 'GET',
url: "https://booksbackend.herokuapp.com/products/" + result._id
}
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
解决方案
基本上,您的 API 服务器代码中应该有 MODEL、CONTROLLES 和 ROUTES。您可以使用exports 和require 来实现它。
ROUTES:应该只有路由部分。
var Express = require('express'),
Router = Express.Router(),
roleController = require('../controllers/role.controller');
Router.route('/addRole').all().post(roleController.addRole);
module.exports = Router;
CONTROLLER:应该有业务逻辑。
var roles = require('../models/role'),
apiHandler = require('../services/api-handler');
// Add role
exports.addRole = function (req, res) {
var newRole = new roles(req.body);
roles.addRole(newRole, function (err) {
if (err) {
res.send(apiHandler.generateErrorResponse('NO_USERS'));
} else {
res.send(apiHandler.generateSuccessResponse('ROLE_ADDED'));
}
});
};
模型:数据库模式和相关查询。
var Mongoose = require('mongoose');
// User schema
var RoleSchema = Mongoose.Schema({
id: {
type: Number,
required: true,
unique: true
},
role: {
type: String,
required: true,
trim: true
},
permission: {
type: Array,
required: true
}
});
var Role = module.exports = Mongoose.model('Role', RoleSchema);
module.exports.addRole = function (newRole, callback) {
newRole.save(callback);
};
APP.js 只有服务器和数据库设置相关的代码应该存在。
在您的情况下,我建议您将 gridfs 代码移至 product.js。
我强烈推荐上述架构。
推荐阅读
- c++ - 脆弱的基类问题会出现在 C++ 中吗?
- intellij-idea - intellij idea 结帐错误:doenst 显示“svn 结帐选项”对话框?
- kotlin - Kotlin 的 fold 是什么让我可以将操作函数放在右括号之后?
- google-cloud-platform - 谷歌云实例显示 SSH 而不是 RDP(Windows 而不是 Linux)
- javascript - 更新到 Codeigniter 3.x 后,为什么在 ajax 调用期间出现 json 解析错误?
- ruby-on-rails - 显示多行错误消息
- mysql - 从 db 表中获取行
- reactjs - 我可以在不违反 React 设计原则的情况下在 reducer 中验证令牌吗?
- java - 为什么java支持255维数组,而在现实生活中我们很少超过2D?
- python - Python Pong Game在1后没有增加点