图像文件下载或在浏览器中显示

时间:2018-01-09 08:48:46

标签: node.js mongodb gridfs koa2

我正在制作一个包含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
    }
  }

工作得很好!

1 个答案:

答案 0 :(得分:0)

其中一个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并不是获取文件所必需的,但它有助于向浏览器表明它应该显示图像而不是将其视为下载。