我正在尝试创建一个webApp,用户可以在其中上传一些图像,为了完成这个任务,我使用了gridfs
。
我弄清楚了如何正确地保存它们,但是当我不得不显示它们时,它们就开始了。
为了保存图像,我使用以下代码
保存图像
const mongoURI = "mongodb://localhost:27017/upload_images";
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.connect(mongoURI);
const conn = mongoose.connection;
// Init gfs
let gfs;
conn.once('open', () => {
// Init stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('uploaded_images'); //collection name
});
// 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: 'uploaded_images' //collection name
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
router.post('/posts', upload.single('file'), (req, res) => {
file = req.file;
if(file){
req.body.post.image_file = file.id;
}
Post.create(req.body.post, (err, post) => {
if(err){
res.redirect('/posts');
} else {
res.redirect('/posts');
}
});
});
图像被正确保存,现在我必须显示它们。
我有一个mongoose
post模式,其中保存了一些数据和上传图像的引用( ObjectId )。
后模式
const mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
image_link: String,
image_file: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'GFS'
}],
brand: String,
model: String,
moto_type: String,
date : {type : Date, default : Date.now},
categories : [{
title: String,
content: String,
}],
comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}],
views: {type: String, default: '0'}
});
module.exports = mongoose.model('Post', PostSchema, 'posts');
和一个gridfs模式,用于在post模式中使用引用。
GridFs模式
const mongoose = require('mongoose');
var gridFsSchema = new mongoose.Schema({});
module.exports = mongoose.model('GFS', gridFsSchema, 'uploaded_images.files');
当我试图显示一个帖子时,我的问题就开始了。
router.get('/posts/:post_id', (req, res) => {
post_id = req.params.post_id;
Post.findById(post_id)
.populate('comments')
.populate('image_file')
.exec((err, post) => {
if(err){
console.log(err)
res.redirect('/posts');
} else {
res.render('posts/show', {post: post})
}
});
});
第一个问题是.populate('image_file')
方法抛出此错误
{ MissingSchemaError: Schema hasn't been registered for model "GFS".
Use mongoose.model(name, schema)
at new MissingSchemaError (/home/pero/motoWebApp/node_modules/mongoose/lib/error/missingSchema.js:22:11)
at NativeConnection.Connection.model (/home/pero/motoWebApp/node_modules/mongoose/lib/connection.js:925:11)
at getModelsMapForPopulate (/home/pero/motoWebApp/node_modules/mongoose/lib/model.js:4434:59)
at populate (/home/pero/motoWebApp/node_modules/mongoose/lib/model.js:3979:21)
at _populate (/home/pero/motoWebApp/node_modules/mongoose/lib/model.js:3949:5)
at utils.promiseOrCallback.cb (/home/pero/motoWebApp/node_modules/mongoose/lib/model.js:3924:5)
at Object.promiseOrCallback (/home/pero/motoWebApp/node_modules/mongoose/lib/utils.js:249:12)
at Function.Model.populate (/home/pero/motoWebApp/node_modules/mongoose/lib/model.js:3923:16)
at model.Query.Query._completeOne (/home/pero/motoWebApp/node_modules/mongoose/lib/query.js:2018:9)
at Immediate.Query.base.findOne.call (/home/pero/motoWebApp/node_modules/mongoose/lib/query.js:2057:10)
at Immediate.<anonymous> (/home/pero/motoWebApp/node_modules/mquery/lib/utils.js:116:16)
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
message:
'Schema hasn\'t been registered for model "GFS".\nUse mongoose.model(name, schema)',
name: 'MissingSchemaError' }
第二个原因是,当我向/posts/:post_id
发出get请求时,我不知道如何显示图像
发布于 2020-12-18 01:28:34
我知道这已经很晚了,但这是为了帮助任何想要更新解决方案的人。由于旧的网格系统将被废弃,我只是分享对我起作用的东西。您可以在正式的MongoDB文档中阅读更多内容。
import express from "express";
import mongoDB from "mongodb";
import assert from "assert";
const dbName = "Your Database"
const app = express();
app.use(express.json());
app.get('/image/:filename', (req, res) => {
mongoDB.MongoClient.connect("Your Mongo Uri",
{
useNewUrlParser:true,
useUnifiedTopology:true
},
(error,client) => {
assert.ifError(error)
const db = client.db(dbName);
var bucket = new mongoDB.GridFSBucket(db);
bucket.openDownloadStreamByName(req.params.filename)
.pipe(res)
});
});
app.listen(4000, () => (console.log("Server Started on port 4000")));
发布于 2019-06-30 16:31:25
我解决了这个问题:
要用gridfs正确地显示图像,您必须遵循以下步骤:
1)
上传文件时,将id保存为模式中的引用,以便在您可以使用.populate method
填充它之后。通过在架构中插入以下行,可以将其保存为引用。
image_file: {
type: mongoose.Schema.Types.ObjectId,
ref: 'GridFs'
},
2)
创建一个grifs模型,作为上载文件的参考。
const mongoose = require('mongoose');
var GridfsSchema = new mongoose.Schema({
filename: String
}, {strict: false});
module.exports = mongoose.model('GridFs', GridfsSchema, 'uploaded_images.files' );
问题中出现的错误是抛出,因为我在外部文件中定义了模型,并且从未导入它。
3)
定义呈现文件的路由:
const express = require('express'),
router = express.Router(),
mongoose = require('mongoose'),
path = require('path'),
multer = require('multer'),
crypto = require('crypto'),
Grid = require('gridfs-stream'),
GridFsStorage = require('multer-gridfs-storage'),
Post = require('../models/post');
const conn = mongoose.connection;
const mongoURI = "mongodb://localhost:27017/moto_website";
// Init gfs
let gfs;
conn.once('open', () => {
// Init stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('uploaded_images'); //collection name
});
router.get('/image/:filename', (req, res) => {
gfs.files.findOne({filename: req.params.filename}, (err, file) => {
if(!file || file.length === 0){
return res.status(404).json({err: 'No File Exists'});
} else {
// Check if is image
if(file.contentType === "image/jpeg" || file.contentType === "image/png"){
// Read output to broswer
const readstream = gfs.createReadStream(file.filename);
readstream.pipe(res);
} else {
res.status(404).json({err: 'Not and image'});
}
}
});
});
现在,每次您进入路径/images/:image_name
时,它都会呈现名称为:image_name
的图像。
4)
设置为src
属性的<img>
标记路径/images/<your_filename_in_gridfs.files>
源
在找到解决方案之前我犯了一些错误
1)我可以检索填充对象,但不能检索给我未定义的属性。这是因为在gridfs模式中,我有一个空对象,所以我什么也找不到。通过在Schema
中定义我解决的属性filename: String
(仅对于文件名属性,其他属性将返回未定义的属性)。如果您也想阅读它们,您必须在gridfs Schema
中编写它们)。请参阅This answer
2)我不知道如何将gridfs文件链接到相关的引用See this answer
https://stackoverflow.com/questions/56818921
复制相似问题