Mongodb позволяет держать в базе не только документы, но и бинарные данные в помощью пакета mongoose-gridfs.
import database from 'database'
import Stream from 'stream'
const mongooseFS = require('mongoose-gridfs')
/**
* Storage
*/
export default class Storage {
/**
* constructor
* @param {string} filename
* @param {*} contentType
* @param {*} stream
* @return {Storage}
*/
constructor({ filename, contentType, stream } = {}) {
const gridfs = mongooseFS({
collection: 'attachments',
model: 'Attachment',
mongooseConnection: database.connection
})
this._filename = filename
this._contentType = contentType
if (stream)
if (Buffer.isBuffer(stream)) {
const uploadStream = new Stream.PassThrough()
uploadStream.end(stream)
this._stream = uploadStream
} else {
this._stream = stream
}
this.model = gridfs.model
return this
}
/**
* readById
* @param {uid} objectId
* @return {Promise<any> | Promise}
*/
static readById(objectId) {
const gridfs = mongooseFS({
collection: 'attachments',
model: 'Attachment',
mongooseConnection: database.connection
})
return new Promise((resolve, reject) => {
gridfs.model.readById(objectId, (error, content) => {
if (error) return reject(error)
resolve(content)
})
})
}
/**
* create or save a file
* @return {Promise<any> | Promise}
*/
save() {
return new Promise((resolve, reject) => {
this.model.write(
{
filename: this._filename,
contentType: this._contentType
},
this._stream,
(error, createdFile) => {
if (error) return reject(error)
resolve(createdFile)
}
)
})
}
}
Подключаем отображение бинарного контента с помощью Express.js.
app.get('/images/:id', async (request, response) => {
const { Storage } = require('.')
try {
const imageBuffer = await Storage.readById(request.params.id)
response.writeHead(200, { 'Content-Type': 'image/jpeg' })
return response.end(imageBuffer, 'binary')
} catch (e) {
return response.send(404, 'Empty data')
}
})