programing

Node.js 및 Mongoose를 사용하여 GridFS를 사용하여 이미지를 저장하는 방법

bestprogram 2023. 7. 16. 13:46

Node.js 및 Mongoose를 사용하여 GridFS를 사용하여 이미지를 저장하는 방법

Node.js가 처음입니다.Node.js 및 Mongoose를 사용하여 이미지와 같은 이진 데이터를 저장하고 검색하기 위해 GridFS를 사용하는 방법에 대한 예를 제공할 수 있는 사람이 있습니까?GridFS에 직접 액세스해야 합니까?

여기서 가장 높은 평가를 받은 답변에 만족하지 못했기 때문에 새로운 답변을 제공합니다.저는 결국 npm을 통해 설치할 수 있는 노드 모듈 'gridfs-stream'(여기에 훌륭한 설명서가 있습니다!)을 사용하게 되었습니다.몽구스와 함께 사용하면 다음과 같이 보일 수 있습니다.

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."));
}

지금까지의 답변은 좋지만, "gridfs-stream"과 같은 추가 추상화에 의존하는 대신 공식 mongodb nodejs 드라이버를 사용하여 이를 수행하는 방법을 여기에 문서화하는 것이 유익할 것이라고 생각합니다.

이전의 한 답변은 실제로 공식 mongodb 드라이버를 사용했지만, 그들은 그리드스토어 API를 사용합니다. 그 이후로 더 이상 사용되지 않습니다. 여기를 참조하십시오.새로운 GridFSBu킷 API를 사용하는 예를 보겠습니다.

질문은 꽤 광범위해서 제 대답은 전체 nodejs 프로그램일 것입니다.여기에는 고속 서버, mongodb 드라이버 설정, 경로 정의 및 GET 및 POST 경로 처리가 포함됩니다.

사용된 Npm 패키지

  • express(이 스니펫을 단순화하기 위한 nodejs 웹 응용프로그램 프레임워크)
  • multter(다중 부품/폼 데이터 요청 처리용)
  • mongodb (공식 mongodb nodejs 드라이버)

GET 사진 경로는 Mongo Object를 사용합니다.이미지를 검색하는 매개 변수로 사용되는 ID입니다.

나는 업로드된 파일을 메모리에 저장하도록 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!");
});

저는 이 주제에 대해 블로그 글을 썼습니다; 이것은 제 대답을 정교하게 만든 것입니다.여기서 사용 가능

추가 독서/영감:

MongoDB GridFS에서 노드로 파일을 저장하는 데 문제가 있습니다.제이에스

답변에서 예를 복사했습니다(크레딧은 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);
  });
});

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.

파일 업로드 라이브러리를 제거하고 다중 부분 헤더 관련 오류가 발생하는 경우 헤더에서 content-type을 제거합니다.

언급URL : https://stackoverflow.com/questions/8135718/how-to-use-gridfs-to-store-images-using-node-js-and-mongoose