图像文件下载或在浏览器中显示
Image file download or show in browser
我正在使用 Node、Koa2、Mongo、GridFS 和 React 制作图片上传应用程序。目前我使用此代码上传文件没有问题:
// HANDLE POST MULTIPART FORM DATA
app.use(async function(ctx, next) {
if (
!ctx.request.is('urlencoded', 'multipart') ||
('POST' != ctx.method && ctx.url === '/uploadFiles')
) return await next()
console.log('POST REQUESTED AT: ', ctx.url)
// HANDLE THIS MIME TYPE SOME OTHER WAY!!!!
var mimeTyp = ''
// WAIT UNTIL CONNECTION IS RESOLVED
const conn = await connectionDB()
// SETUP THE MAIN DATABASE
const testDB = conn.db('gridfsTestDB')
// SETUP FS.FILES CONNECTION
const fsFiles = testDB.collection('fs.files')
// SET THE BUCKET FOR GRIDFS
const bucket = new mongodb.GridFSBucket(testDB)
// DECLARE WHERE YOU WANT THE FILE TO BE UPLOADED AND YOU CAN SUPPLY ADITIONAL DATA HERE TO THE FILE
const writeStream = bucket.openUploadStream()
const readStream = bucket.openDownloadStream()
console.log(readStream)
// ASYNC-BUSBOY MIDDLEWARE HANDLES FORM SUBMITION AND FILE PIPEING
const { fields } = await AsyncBusboy(ctx.req, {
// THIS IS CALLED FOR EACH CHUNK OF FILE SENT THROUGH PIPE
onFile: function(fieldname, file, filename, encoding, mimetype) {
console.log('start pipe')
console.log('MIMETYPE', mimetype)
mimeTyp = mimetype
file.pipe(writeStream)
console.log('end pipe')
}
})
// HERE WE WAIT FOR STREAM OF THE FILE TO FINISH AND THEN WE APPEND METADATA TO IT
await onStreamFinish(writeStream)
})
但是我在从 Mongo 读取文件并将其显示给用户时遇到了问题。如何使用异步方法做到这一点? createReadStream
我想但没能实现它。我只是在寻找有关使用方法的指导,我会尝试一下。
编辑(感谢 Rich Churcher):
try {
const conn = await connectionDB()
const testDB = conn.db('gridfsTestDB')
const fsFiles = testDB.collection('fs.files')
const bucket = new mongodb.GridFSBucket(testDB)
const metadataFile = await getfileToDownload(ctx.params.id, fsFiles)
const readStream = bucket.openDownloadStream(ObjectId(ctx.params.id))
console.log(metadataFile)
ctx.set('Content-Type', metadataFile.contentType)
ctx.set(
'Content-Disposition',
'inline; filename="' + normalizeString(metadataFile.metadata.DocumentName) + '"'
)
ctx.body = readStream
} catch (err) {
console.log(err)
ctx.status = 503
ctx.body = {
message: 'Unable to preview the document. Error: ' + err.message
}
}
工作正常!
Koa 示例之一是 stream-file,这是一个很好的起点。通常这只是将 ctx.body
设置为流的情况。显然您想使用 GridFS 作为源而不是本地文件系统。
我注意到 gridfs-stream,我认为这会让您的生活更轻松。但是,假设您不想添加其他依赖项。这是下载的最低限度处理程序:
const { GridFSBucket, MongoClient } = require('mongodb')
// ...
app.use(async ctx => {
const connection = await MongoClient.connect('mongodb://localhost:27017')
const db = connection.db('gfs-example')
const bucket = new GridFSBucket(db, { bucketName: 'images' })
ctx.type = 'image/jpg'
ctx.body = bucket.openDownloadStreamByName('foo.jpg')
})
看起来您已经设置了自己的数据库工具,我只是添加了一个连接以使这个答案更加独立。请注意,设置 ctx.type
并不是获取文件所必需的,但它有助于向浏览器表明它应该显示图像而不是将其视为下载。
我正在使用 Node、Koa2、Mongo、GridFS 和 React 制作图片上传应用程序。目前我使用此代码上传文件没有问题:
// HANDLE POST MULTIPART FORM DATA
app.use(async function(ctx, next) {
if (
!ctx.request.is('urlencoded', 'multipart') ||
('POST' != ctx.method && ctx.url === '/uploadFiles')
) return await next()
console.log('POST REQUESTED AT: ', ctx.url)
// HANDLE THIS MIME TYPE SOME OTHER WAY!!!!
var mimeTyp = ''
// WAIT UNTIL CONNECTION IS RESOLVED
const conn = await connectionDB()
// SETUP THE MAIN DATABASE
const testDB = conn.db('gridfsTestDB')
// SETUP FS.FILES CONNECTION
const fsFiles = testDB.collection('fs.files')
// SET THE BUCKET FOR GRIDFS
const bucket = new mongodb.GridFSBucket(testDB)
// DECLARE WHERE YOU WANT THE FILE TO BE UPLOADED AND YOU CAN SUPPLY ADITIONAL DATA HERE TO THE FILE
const writeStream = bucket.openUploadStream()
const readStream = bucket.openDownloadStream()
console.log(readStream)
// ASYNC-BUSBOY MIDDLEWARE HANDLES FORM SUBMITION AND FILE PIPEING
const { fields } = await AsyncBusboy(ctx.req, {
// THIS IS CALLED FOR EACH CHUNK OF FILE SENT THROUGH PIPE
onFile: function(fieldname, file, filename, encoding, mimetype) {
console.log('start pipe')
console.log('MIMETYPE', mimetype)
mimeTyp = mimetype
file.pipe(writeStream)
console.log('end pipe')
}
})
// HERE WE WAIT FOR STREAM OF THE FILE TO FINISH AND THEN WE APPEND METADATA TO IT
await onStreamFinish(writeStream)
})
但是我在从 Mongo 读取文件并将其显示给用户时遇到了问题。如何使用异步方法做到这一点? createReadStream
我想但没能实现它。我只是在寻找有关使用方法的指导,我会尝试一下。
编辑(感谢 Rich Churcher):
try {
const conn = await connectionDB()
const testDB = conn.db('gridfsTestDB')
const fsFiles = testDB.collection('fs.files')
const bucket = new mongodb.GridFSBucket(testDB)
const metadataFile = await getfileToDownload(ctx.params.id, fsFiles)
const readStream = bucket.openDownloadStream(ObjectId(ctx.params.id))
console.log(metadataFile)
ctx.set('Content-Type', metadataFile.contentType)
ctx.set(
'Content-Disposition',
'inline; filename="' + normalizeString(metadataFile.metadata.DocumentName) + '"'
)
ctx.body = readStream
} catch (err) {
console.log(err)
ctx.status = 503
ctx.body = {
message: 'Unable to preview the document. Error: ' + err.message
}
}
工作正常!
Koa 示例之一是 stream-file,这是一个很好的起点。通常这只是将 ctx.body
设置为流的情况。显然您想使用 GridFS 作为源而不是本地文件系统。
我注意到 gridfs-stream,我认为这会让您的生活更轻松。但是,假设您不想添加其他依赖项。这是下载的最低限度处理程序:
const { GridFSBucket, MongoClient } = require('mongodb')
// ...
app.use(async ctx => {
const connection = await MongoClient.connect('mongodb://localhost:27017')
const db = connection.db('gfs-example')
const bucket = new GridFSBucket(db, { bucketName: 'images' })
ctx.type = 'image/jpg'
ctx.body = bucket.openDownloadStreamByName('foo.jpg')
})
看起来您已经设置了自己的数据库工具,我只是添加了一个连接以使这个答案更加独立。请注意,设置 ctx.type
并不是获取文件所必需的,但它有助于向浏览器表明它应该显示图像而不是将其视为下载。