Как использовать GridFS для хранения изображений с использованием Node.js и Mongoose - PullRequest
17 голосов
/ 15 ноября 2011

Я новичок в Node.js.Может ли кто-нибудь предоставить мне пример того, как использовать GridFS для хранения и извлечения двоичных данных, таких как изображения, с использованием Node.js и Mongoose?Нужен ли мне прямой доступ к GridFS?

Ответы [ 4 ]

22 голосов
/ 09 апреля 2014

Меня не удовлетворил ответ с наивысшим рейтингом, поэтому я предоставляю новый: в итоге я использовал модуль узла 'gridfs-stream' (отличная документация!), Который может бытьустанавливается через нпм.С ним и в сочетании с mongoose это может выглядеть так:

var fs = require('fs');
var mongoose = require("mongoose");
var Grid = require('gridfs-stream');
var GridFS = Grid(mongoose.connection.db, mongoose.mongo);

function putFile(path, name, callback) {
    var writestream = GridFS.createWriteStream({
        filename: name
    });
    writestream.on('close', function (file) {
      callback(null, file);
    });
    fs.createReadStream(path).pipe(writestream);
}

Обратите внимание, что путь - это путь к файлу в локальной системе.

Что касается функции чтения изфайл, в моем случае мне просто нужно передать файл в браузер (используя экспресс):

try {
    var readstream = GridFS.createReadStream({_id: id});
    readstream.pipe(res);
} catch (err) {
    log.error(err);
    return next(errors.create(404, "File not found."));
}
9 голосов
/ 09 ноября 2017

Ответы пока хорошие, но я считаю, что было бы полезно документально подтвердить, как это сделать, используя официальный драйвер mongodb nodejs вместо того, чтобы полагаться на другие абстракции, такие как "gridfs-stream".

В одном предыдущем ответе действительно использовался официальный драйвер mongodb, однако они используют Gridstore API; который с тех пор устарел, см. здесь . Мой пример будет использовать новый GridFSBucket API .

Вопрос довольно широкий, поэтому моим ответом будет целая программа nodejs. Это будет включать в себя настройку экспресс-сервера, драйвера mongodb, определение маршрутов и обработку маршрутов GET и POST.

Используемые пакеты Npm

  • express (инфраструктура веб-приложения nodejs для упрощения этого фрагмента)
  • multer (для обработки запросов multipart / form-data)
  • mongodb (официальный драйвер mongodb nodejs)

Маршрут фото GET принимает идентификатор объекта Mongo в качестве параметра для получения изображения.

Я настраиваю Multer для сохранения загруженного файла в памяти. Это означает, что файл фотографии не будет записываться в файловую систему в любое время, а вместо этого будет передаваться прямо из памяти в GridFS.


/**
 * NPM Module dependencies.
 */
const express = require('express');
const photoRoute = express.Router();

const multer = require('multer');
var storage = multer.memoryStorage()
var upload = multer({ storage: storage, limits: { fields: 1, fileSize: 6000000, files: 1, parts: 2 }});

const mongodb = require('mongodb');
const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;
let db;

/**
 * NodeJS Module dependencies.
 */
const { Readable } = require('stream');

/**
 * Create Express server && Routes configuration.
 */
const app = express();
app.use('/photos', photoRoute);

/**
 * Connect Mongo Driver to MongoDB.
 */
MongoClient.connect('mongodb://localhost/photoDB', (err, database) => {
  if (err) {
    console.log('MongoDB Connection Error. Please make sure that MongoDB is running.');
    process.exit(1);
  }
  db = database;
});

/**
 * GET photo by ID Route
 */
photoRoute.get('/:photoID', (req, res) => {
  try {
    var photoID = new ObjectID(req.params.photoID);
  } catch(err) {
    return res.status(400).json({ message: "Invalid PhotoID in URL parameter. Must be a single String of 12 bytes or a string of 24 hex characters" }); 
  }

  let bucket = new mongodb.GridFSBucket(db, {
    bucketName: 'photos'
  });

  let downloadStream = bucket.openDownloadStream(photoID);

  downloadStream.on('data', (chunk) => {
    res.write(chunk);
  });

  downloadStream.on('error', () => {
    res.sendStatus(404);
  });

  downloadStream.on('end', () => {
    res.end();
  });
});

/**
 * POST photo Route
 */
photoRoute.post('/', (req, res) => {
  upload.single('photo')(req, res, (err) => {
    if (err) {
      return res.status(400).json({ message: "Upload Request Validation Failed" });
    } else if(!req.body.name) {
      return res.status(400).json({ message: "No photo name in request body" });
    }

    let photoName = req.body.name;

    // Covert buffer to Readable Stream
    const readablePhotoStream = new Readable();
    readablePhotoStream.push(req.file.buffer);
    readablePhotoStream.push(null);

    let bucket = new mongodb.GridFSBucket(db, {
      bucketName: 'photos'
    });

    let uploadStream = bucket.openUploadStream(photoName);
    let id = uploadStream.id;
    readablePhotoStream.pipe(uploadStream);

    uploadStream.on('error', () => {
      return res.status(500).json({ message: "Error uploading file" });
    });

    uploadStream.on('finish', () => {
      return res.status(201).json({ message: "File uploaded successfully, stored under Mongo ObjectID: " + id });
    });
  });
});

app.listen(3005, () => {
  console.log("App listening on port 3005!");
});

Я написал пост в блоге на эту тему; Это разработка моего ответа. В наличии здесь

Дальнейшее чтение / вдохновение:

8 голосов
/ 15 ноября 2011

Предлагаю взглянуть на этот вопрос: Проблема с MongoDB GridFS Сохранение файлов с Node.JS

Скопированный пример из ответа (кредит переходит к christkv):

// You can use an object id as well as filename now
var gs = new mongodb.GridStore(this.db, filename, "w", {
  "chunk_size": 1024*4,
  metadata: {
    hashpath:gridfs_name,
    hash:hash,
    name: name
  }
});

gs.open(function(err,store) {
  // Write data and automatically close on finished write
  gs.writeBuffer(data, true, function(err,chunk) {
    // Each file has an md5 in the file structure
    cb(err,hash,chunk);
  });
});
3 голосов
/ 10 апреля 2012

Похоже, что writeBuffer с тех пор устарел.

/Users/kmandrup/private/repos/node-mongodb-native/HISTORY:
   82  * Fixed dereference method on Db class to correctly dereference Db reference objects. 
   83  * Moved connect object onto Db class(Db.connect) as well as keeping backward compatibility.
   84: * Removed writeBuffer method from gridstore, write handles switching automatically now.
   85  * Changed readBuffer to read on Gridstore, Gridstore now only supports Binary Buffers no Strings anymore.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...