首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何显示mongodb网格资源中的图像

如何显示mongodb网格资源中的图像
EN

Stack Overflow用户
提问于 2019-06-29 15:53:56
回答 2查看 2.8K关注 0票数 0

我正在尝试创建一个webApp,用户可以在其中上传一些图像,为了完成这个任务,我使用了gridfs

我弄清楚了如何正确地保存它们,但是当我不得不显示它们时,它们就开始了。

为了保存图像,我使用以下代码

保存图像

代码语言:javascript
运行
复制
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 )。

后模式

代码语言:javascript
运行
复制
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模式

代码语言:javascript
运行
复制
const mongoose = require('mongoose');

var gridFsSchema = new mongoose.Schema({});

module.exports = mongoose.model('GFS', gridFsSchema, 'uploaded_images.files');

当我试图显示一个帖子时,我的问题就开始了。

代码语言:javascript
运行
复制
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')方法抛出此错误

代码语言:javascript
运行
复制
{ 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请求时,我不知道如何显示图像

EN

回答 2

Stack Overflow用户

发布于 2020-12-18 01:28:34

我知道这已经很晚了,但这是为了帮助任何想要更新解决方案的人。由于旧的网格系统将被废弃,我只是分享对我起作用的东西。您可以在正式的MongoDB文档中阅读更多内容。

代码语言:javascript
运行
复制
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")));
票数 1
EN

Stack Overflow用户

发布于 2019-06-30 16:31:25

我解决了这个问题:

要用gridfs正确地显示图像,您必须遵循以下步骤:

1)

上传文件时,将id保存为模式中的引用,以便在您可以使用.populate method填充它之后。通过在架构中插入以下行,可以将其保存为引用。

代码语言:javascript
运行
复制
image_file: {
        type: mongoose.Schema.Types.ObjectId, 
        ref: 'GridFs' 
    },

2)

创建一个grifs模型,作为上载文件的参考。

代码语言:javascript
运行
复制
const mongoose = require('mongoose');

var GridfsSchema = new mongoose.Schema({
    filename: String
}, {strict: false});

module.exports = mongoose.model('GridFs', GridfsSchema, 'uploaded_images.files' );

问题中出现的错误是抛出,因为我在外部文件中定义了模型,并且从未导入它。

3)

定义呈现文件的路由:

代码语言:javascript
运行
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56818921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档