【问题标题】:How can I save my image data from front end to Mongoose database using Node.js server如何使用 Node.js 服务器将图像数据从前端保存到 Mongoose 数据库
【发布时间】:2017-06-30 14:31:42
【问题描述】:

我有一个使用 node.js 的后端和一个使用 jquery、javascript、ajax 和 bootstrap 的前端。我想从前端上传一张图片并将其保存到猫鼬数据库中。此处文件加载成功,图像将位于名为 /public/img 的位置。但是如何使用 API 调用将这些图像信息保存到数据库中。
以下是我的代码:

后端代码 Node.js、Mongoose

/server.js

var express =   require("express");
var multer  =   require('multer');
var path = require('path');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');

var app = express();
   app.appname="photogallery";

//config mongoose
  app.db = mongoose.createConnection('localhost/'+app.appname);
  app.db.on('error', console.error.bind(console, 'mongoose connection error: '));
  app.db.once('open', function () {
  //Storage is all good
  });

//Routes and acl
  var router = express.Router();
  require('./routes')(app, router, passport);

var file_url = '';

var storage =   multer.diskStorage({
  destination: function (req, file, callback) {
    callback(null, 'public/img/');
  },
  filename: function (req, file, callback) {
    callback(null, file.fieldname + '-' + Date.now());
     file_url = file.fieldname + '-' + Date.now() + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]
  callback(null, file_url);
  }
});

var upload = multer({ storage : storage}).single('userPhoto');

app.use(express.static(path.join(__dirname, '/public/')));

app.post('/api/photo',function(req,res){
    upload(req,res,function(err) {
        if(err) {
            return res.end("Error uploading file.");
        }
       // res.end("File is uploaded");
      res.json({error_code:0,err_desc:null,file_url:'img/'+file_url});
      /*Now I want to save this file_url to image_url using api /api/photoGallery, please help me to save these information to the db */ 
    });
});

//config express
  app.set('secret','thisshouldnotbeinplaintext');
  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(bodyParser.json());
  app.use(passport.initialize());
  app.use(router);


app.listen(5050,function(){
    console.log("Working on port 5050");
});

/api/requests.js

'use strict';
  var passport = require('passport');
  var app = require('../app');

exports.init = function(pp) {
    passport = pp;
    app = pp;
    return exports;
};

exports.root = function(req, res) {
    res.send("Running");
  };

//Add Image Data
exports.addData = function(req, res) {
  var addData = req.app.db.model('Data');
  var data = {  image_title  : req.body.image_title,
                image_url    : "http://localhost:5050/"+req.body.image_url
              }
  var query = addData(data);
  query.save(function(err){
    if(err){
      console.log(err.toString());
    }
  console.log('Image Saved Successfully');
  res.json({ success: true });
 });
};

/schema/Data.js

'use strict';

exports = module.exports = function(app, mongoose) {
    var dataSchema = new mongoose.Schema({
        image_title  :  { type: String, unique: true,  lowercase: true },
        image_url    :  { type: String, unique: true,  lowercase: true }
    });
    app.db.model('Data', dataSchema);
};

/models.js

'use strict';

module.exports = function(app, mongoose) {
    //Mongoose Schemas
    require('./schema/Data')(app, mongoose);
};

/routes.js

 'use strict';

module.exports = function(app, router, passport) {

    var requests = require('./api/requests').init(passport);
    router.get('/', requests.root);

    router.post('/api/addPhoto/v1', requests.addData);
    router.get('/api/getPhoto/v1', requests.getPhoto);

};

例如 Json 将如下所示

{
   image_title: exampleImage,
   image_url: xyzscjnscncsl.exampleImage.png
}

前端代码 Jquery、JavaScript、Ajax、HTML

/public/index.html

<div class="modal fade" id="myModal" role="dialog">
    <div class="modal-dialog">
        <!-- Modal content-->
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <h4 class="modal-title">Please Upload Image</h4>
            </div>
            <form id="uploadForm" enctype="multipart/form-data" action="/api/photo" method="post">
            <div class="modal-body">
                <div class="form-group">
                    <input type="text" class="form-control" id="imagetitle" placeholder="Image Title">
                </div>
                 <div class="form-group">
                     <input type="file" class="form-control" id="input-image" name="userPhoto" accept="image/*">
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Cancle</button>
                <button type="submit" class="btn btn-default" value="Upload Image" name="submit">Save</button>
            </div>
                <span id = "status"></span>
            </form>
        </div>
    </div>
</div>

/public/javascript/image.js

如何使用 API 调用将图像数据从这里保存到 mongoose db?

$(document).ready(function() {
    $('#uploadForm').submit(function() { 
        $("#status").empty().text("File is uploading...");
        $(this).ajaxSubmit({
            error: function(xhr) {
                status('Error: ' + xhr.status);
            },
            success: function(response) {
                console.log(response)
                $("#status").empty().text(response);
            }
        });
        return false;
    });    
});

【问题讨论】:

  • 我只想说“不要”。这不是将图像数据保存到数据库中的好方法。数据库能够但未针对大型二进制块的块存储进行优化。您最好将其保存到某些块存储服务(例如 S3)中,然后将其 URL 放入您的数据库中。
  • 好的,谢谢,但这不是我的问题的解决方案。在这里,我不想将其保存在 S3 中。我想将它保存在我的数据库中。请任何人帮助我,我是这些技术的新手。

标签: javascript jquery ajax node.js mongodb


【解决方案1】:

对于大多数项目,我不建议这样做(正如 Paul 评论的那样),但这并不复杂。

从客户端获取图像文件后,您读取图像数据 (fs.readFile) 并使用缓冲区将其编码为 base64 并保存到您的数据库中,这样您将使用更少的空间来存储数据。然后在需要二进制文件时解码 base64 数据。

fs.readFile('foo.png', function(err, data) {
   const base64img = new Buffer(data).toString('base64');
});

有一些 npm 模块可以让这更简单一些,例如 base64-img

【讨论】:

    【解决方案2】:

    我建议您使用 busboy 而不是 multer,因为 multer 保存到磁盘,busboy 返回一个流,您可以通过管道传输到任何您想要的内容(甚至是 mongoDB)。

    Gridfs-stream 是一个很好的模块,可以使用 gridfs 功能将数据流式传输到 mongoDB。

    这是它们的基本用法:

    var Busboy = require('busboy');
    var gfs = require('gridfs-stream')(mongoose.connection.db, mongoose.mongo)
    
    
    //express middleware:
    function (req, res) {
        var busboy = new Busboy({ headers: req.headers, limits: { fileSize: 1024, files: 1 } });
        busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
            var ws = gfs.createWriteStream({ filename: filename, content_type: mimetype});
            ws.on('error', function(err) {
                console.error(err);
                res.send(500, err);
            });
            ws.on('finish', () => {/*do something when streaming ends*/});
            file.pipe(ws);
        }
        busboy.on('error', function(err) {
            console.error(err);
            res.send(500, err);
        });
        req.pipe(busboy);
    }
    

    【讨论】:

    • 这里有一个关于gridfs的链接:docs.mongodb.com/manual/core/gridfs
    • 谢谢,但是我想通过/api/photoGallery,json({image_title: myImage, image_url: xxxxxmyImage.png})将图片信息存储在我的数据库中。请查看我的架构、模型、mongo 连接、路由。请帮我将这些图像信息保存到数据库中。
    • 您可以在 createWriteStream 函数中将元数据添加到文件中,或者在流的完成事件中跟进对 mongoose API 的调用。
    【解决方案3】:

    /* 这里是解决方案 */

    /server.js

    var express =   require("express");
    var multer  =   require('multer');
    var path = require('path');
    var passport = require('passport');
    var mongoose = require('mongoose');
    var bodyParser = require('body-parser');
    
    
    
    var app = express();
    app.appname="photogallery";
    
    //config mongoose
    app.db = mongoose.createConnection('localhost/'+app.appname);
    app.db.on('error', console.error.bind(console, 'mongoose connection error: '));
    app.db.once('open', function () {
    });
    
    
    //config data models
    require('./models')(app, mongoose);
    
    //Routes and acl
    var router = express.Router();
    require('./routes')(app, router, passport);
    
    /* Image Logic */
    var file_url = '';
    var storage =   multer.diskStorage({
      destination: function (req, file, callback) {
        callback(null, 'public/img/');
      },
      filename: function (req, file, callback) {
        callback(null, file.fieldname + '-' + Date.now());
    
          file_url = file.fieldname + '-' + Date.now() + '.' + file.originalname.split('.')[file.originalname.split('.').length -1];
          callback(null, file_url);
      }
    });
    
    var upload = multer({ storage : storage}).single('userPhoto');
    
    app.use(express.static(path.join(__dirname, '/public/')));
    
    app.post('/api/photo',function(req,res){
        upload(req,res,function(err) {
            if(err) {
                return res.end("Error uploading file.");
            }
            //res.end("File is uploaded");
            //console.log("file_url", file_url);
            res.json({error_code:0,err_desc:null, file_url:'img/'+file_url});
        });
    });
    
    //config express
    app.set('secret','thisshouldnotbeinplaintext');
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    app.use(passport.initialize());
    app.use(router);
    
    app.listen(5050,function(){
        console.log("Working on port 5050");
    });
    

    /api/requests.js

        'use strict';
    
        var jwt = require('jsonwebtoken');
        var passport = require('passport');
    
        exports.init = function(pp) {
            passport = pp;
            return exports;
        };
    
        exports.root = function(req, res) {
            res.send("Running");
        };
    
    /* Save Image Data Function */
    
        exports.addData = function(req, res) {
            var addData = req.app.db.model('Data');
            var data = {
                img_title   : req.body.img_title,
                img_url     : "http://localhost:5050/"+req.body.img_url
            }
            var query = addData(data);
            query.save(function (err, data) {
                if (err) {
                    console.log(err.toString());
                } else {
                    console.log('Image saved Successfully');
                    res.json(data);
                }
            });
        };
    
    /* Get Image Data Function */
        exports.getPhoto = function(req, res) {
                var getPhoto = req.app.db.model("Data");
                var query = getPhoto.find(function(err, data){
                    if(err) {
                        console.log("Not Found");
                    } else  {
                        res.json({'data': data});
                    }
                });
            };
    

    /schema/Data.js

    'use strict';
    
    module.exports = function(app, mongoose) {
        var dataSchema = new mongoose.Schema({
            img_title        : { type: String, default: '' },
            img_url          : { type: String, default: '' }
    
        });
        app.db.model('Data', dataSchema);
    };
    

    /models.js

    'use strict';
    
    module.exports = function(app, mongoose) {
        //Mongoose Schemas
        require('./schema/Data')(app, mongoose);
    }
    

    /routes.js

    'use strict';
    
    module.exports = function(app, router, passport) {
    
        var requests = require('./api/requests').init(passport);
        router.get('/', requests.root);
    
        router.post('/api/addPhoto/v1', requests.addData);
        router.get('/api/getPhoto/v1', requests.getPhoto);
    
    };
    

    /public/index.html

    <div class="modal fade" id="myModal" role="dialog">
        <div class="modal-dialog">
            <!-- Modal content-->
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal">&times;</button>
                    <h4 class="modal-title">Please Upload Image</h4>
                </div>
                <form id="uploadForm" enctype="multipart/form-data" action="/api/photo" method="post">
                <div class="modal-body">
                    <div class="form-group">
                        <input type="text" class="form-control" id="imagetitle" placeholder="Image Title">
                    </div>
                     <div class="form-group">
                         <input type="file" class="form-control" id="input-image" name="userPhoto" accept="image/*">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancle</button>
                    <button type="submit" class="btn btn-default" value="Upload Image" name="submit">Save</button>
                </div>
                    <span id = "status"></span>
                </form>
            </div>
        </div>
    </div>
    

    /public/javascript/image.js

    /* 如何使用api调用将图像数据从前端保存到mongoose */

    $(document).ready(function() {
         $('#uploadForm').submit(function() {
             $("#status").empty().text("File is uploading...");
             var imageTitle = $("#imagetitle").val();
            $(this).ajaxSubmit({
    
                error: function(xhr) {
                        status('Error: ' + xhr.status);
                },
    
                success: function(response) {
                    var localFile = response.file_url;
                    $.ajax({
                        url: "/api/addPhoto/v1",
                        data: {
                            img_title: imageTitle,
                            img_url: localFile
                        },
                        method: 'post',
                        dataType: 'json',
                        success: function(data) {
                            var html = "";
                                html+= "<div class='col-md-3 col-md-offset-1'>";
                                html+= "<div class='img-box imgClass'>";
                                html+= "<img src='"+data.img_url+"'>";
                                html+= "</div> </div>";
                            $('.myimage').append(html);
                            $('#myModal').modal('hide');
    
                        },
                        error: function(xhr, status) {
                            alert("Sorry, there was a problem!");
                        }
                    });
                }
             });
           return false;
        });
    
     });
    
     $(function(){
         $.get("/api/getPhoto/v1", function(response) {
             //console.log(response.data.length);
             var html = "";
             for(var i = 0; i< response.data.length ; i++){
                    html+= "<div class='col-md-3 col-md-offset-1'>";
                    html+= "<div class='img-box imgClass'>";
                    html+= "<img src='"+response.data[i].img_url+"'>";
                    html+= "</div> </div>"
             }
             $('.myimage').html(html);
         });
    
     });
    

    【讨论】:

      猜你喜欢
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      相关资源
      最近更新 更多