使用Node,Express和Multer将文件上传到MongoDB? 我应该使用Multer还是GRIDfs?

问题描述 投票:0回答:2

您好,我在heroku上运行了一个最终项目,使用MongoLab和Multer上传照片似乎正常,但是几小时或更短的时间后,照片从页面上消失了,但留下了img占位符和其他字段,例如名称或日期区域。

这是Heroku还是Mongolab的问题,还是仅仅是免费帐户,原因是免费帐户? 也没有关系,只要上传一张照片或十几张照片仍会消失。

你可以帮帮我吗? 是否存在乱码,棘手的代码行,或者我对Multer或数据库犯错的内容? 我已经在Web和Stack-Overflow上进行了深入研究,我发现了一个名为GRIDfs的东西,但我不知道这样是否可行。 你能告诉我我是否过分严谨吗?

这是我对Multer的代码:

var express        = require("express"),
    body_parser    = require("body-parser"),
    multer         = require("multer"),
    mongoose       = require("mongoose");

    var app = express();

    //connect my local database to MongoLab database   

    var url = process.env.DATABASE || "mongodb://localhost/black_hat";

    mongoose.connect(url);

混合机配置

var storage = multer.diskStorage({
destination: function(req, file, callback){
    callback(null, "./public/uploads");
},
filename: function(req, file, callback){
    callback(null, Date.now() + file.originalname);
}
  });

var upload = multer({storage : storage}).single("image");

我的POST路线

    app.post("/fotos_videos", isLoggedIn, function(req, res) {
    upload(req, res, function(err) {
        if(err){
            return res.end("Error uploading file");
        }
        // get data from form
        var newName = req.body.name,
            newCover = "/uploads/" + req.file.filename;
        // Packing into an object
        var newCollage = {
            name : newName,
            cover: newCover
        };
        //create new album
        Collage.create(newCollage, function(err, collage) {
            if(err){
                console.log(err);
            } else {
                // console.log(collage);
                res.redirect("/fotos_videos");
            }
        });
    });
});

我上传图片的表格

  <div style="width=30%; margin: 30px auto" > <form action="/fotos_videos" method="POST" enctype="multipart/form-data"> <div class="form-group"> <label>Album Name</label> <input type="text" name="name" placeholder="Album Name" class="form-control"> </div> <div class="form-group"> <label>Choose Album Cover</label> <input type="file" name="image" placeholder="image url" class="form-control" required> </div> <div class="form-group"> <button class="btn btn-lg btn-primary btn-block">Upload</button> </div> </form> <a href="/fotos_videos">Back</a> </div> 

最后是我的拼贴模型

var mongoose = require("mongoose");

// Schema 
var collageSchema = new mongoose.Schema({
    name : String,
    cover : String,
    photos: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: "Photo"
    }] 
});

var Collage = mongoose.model("Collage", collageSchema);

module.exports = Collage;

任何帮助将不胜感激。

node.js mongodb mongoose gridfs multer
2个回答
0
投票

我不知道这是否有帮助。 但据我了解,multer是用于从用户那里获取数据的东西(例如上传的图片)。 它不做持久存储。 如果要存储数据(大文件,如图像),则应使用gridfs-stream

一旦数据来自用户,您应该创建一个到GridFs的读取流。


0
投票

如果要将图像保存到数据库,则不应该具有“ dest”属性。 multer的实现也是错误的,也许是因为这是一个古老的问题,以前的api就是这样。 在这里你应该做什么。

配置您的multer:

const multer = require("multer");
const upload = multer({
  limits: { fileSize: 5000000 },
  fileFilter(req, file, cb) {
    if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) { //allowed file extensions
      return cb(new Error("please upload png,jpeg or jpg"));
    }
    cb(undefined, true);
  }
});

然后创建一个端点。 你已经有这个了

app.post("/fotos_videos", isLoggedIn, function(req, res) {
   upload(req, res, function(err) { 

这种实现是错误的。 Upload是一种中间件,如果您想添加身份验证,则只有经过身份验证的用户才能访问此端点。 因此我们需要调整此端点。

另外,您还需要为上载定义一个架构,以将其保存到数据库。 假设您创建了一个名为uploads的模型,并对此进行了建模。 我们不需要用猫鼬来验证它,因为multer已经在处理它。 确保从删除配置中删除dest属性。 因为如果不删除,multer会将文件保存到文件夹,因此我们的async (req,res){}函数将无法访问该文件,因此我们无法将其保存到数据库。

uploads:{type:Buffer} //将其包含在您的上传模式中

然后在此文件中调用上传模型。

router.post(
  "/fotos_videos/me/uploads", isLoggedIn,
  upload.single("uploads"),  //uploads is just a random name when u upload from postman, form form-data,put "uploads" in key field
  async (req, res) => {
    req.upload.uploads = req.file.buffer;//i explain down below
    await req.upload.save();
    res.send();
  },
  (err, req, res) => {
    res.status(400).send("error happned");
  }
);

我们不将图片存储在文件系统中。 原因是几乎所有部署平台都需要我们获取代码并将其推送到其服务器上的存储库中。 因此,每次部署时文件系统都会被擦除,这意味着部署时我们将丢失数据。 因此,我们将在用户模型中添加一个字段以将二进制数据的图像存储在数据库中,而不是将图像存储在文件系统中。

现在是时候从数据库中获取我们的图像了。 为此,您需要一条新路线

router.get("/fotos_videos/:id/uploads", async (req, res) => {
  try {
    const upload = await Uploads.findById(req.params.id);
    if (!upload || !upload.uploads) {
      throw new Error("no image found");
    }
    res.set("Content-Type", "image/png");
    res.send(upload.uploads);
  } catch (e) {
    res.status(400).send(e.message);
  }
});
© www.soinside.com 2019 - 2024. All rights reserved.