不久前,我在Twitter上发布了自己的最新作品,即从MongoDB GridFS传输文件进行下载(而不是将整个文件存储到内存中然后提供服务),这是我取得的一个小胜利。 我答应就此事写博客,但不幸的是,我的特定用法与我的项目的领域有点相关,所以我不能仅仅展示它。 因此,我整理了一个示例node.js + GridFS应用程序 ,并在github上进行了共享,并将使用本文来解释我是如何实现的。

GridFS模块

首先,特殊道具去tjholowaychuk谁在#node.js的IRC频道作出回应时,我问,如果任何人有运气使用GridFS的从猫鼬 。 我得到的很多代码都来自他与我分享的要旨。 无论如何,到代码。 我将描述如何使用gridfs,并在完成基础工作后说明从GridFS流式传输文件的过程是如此简单。

我创建了一个gridfs模块,该模块基本上通过mongoose(我在整个应用程序中使用)访问GridStore,该模块还可以共享将mongoose连接到mongodb服务器时创建的数据库连接。

mongoose = require "mongoose"
request  = require "request"GridStore = mongoose.mongo.GridStore
Grid      = mongoose.mongo.Grid
ObjectID = mongoose.mongo.BSONPure.ObjectID

如果我们不能在mongodb中添加任何文件,我们将无法获取文件,因此让我们创建一个putFile操作。

exports.putFile = (path, name, options..., fn) ->db = mongoose.connection.dboptions = parse(options)options.metadata.filename = namenew GridStore(db, name, "w", options).open (err, file) ->return fn(err)  if errfile.writeFile path, fnparse = (options) ->opts = {}if options.length > 0opts = options[0]if !opts.metadataopts.metadata = {}opts

实际上,这只是委托给GridStore中存在的putFile操作(作为mongodb模块的一部分)。 我也有一些逻辑来解析选项,如果没有提供默认值,则提供默认值。 要注意的一个有趣功能是,我将文件名存储在元数据中,因为当时我遇到了一个有趣的问题,即从gridFS检索的文件将id作为文件名(即使在mongo中查看发现文件名实际上是在数据库)。

现在进行get操作。 此方法的原始实现只是通过调用store.readBuffer()将内容作为缓冲区传递给所提供的回调,但是现在已更改为将结果存储对象传递给回调。 其值是调用者可以使用商店对象来访问元数据,contentType和其他详细信息。 用户还可以确定他们想如何读取文件(进入内存还是使用ReadableStream)。

exports.get = (id, fn) ->db = mongoose.connection.dbid = new ObjectID(id)store = new GridStore(db, id, "r",root: "fs")store.open (err, store) ->return fn(err)  if err# band-aidif "#{store.filename}" == "#{store.fileId}" and store.metadata and store.metadata.filenamestore.filename = store.metadata.filenamefn null, store

这段代码有一个小问题,它检查文件名和fileId是否相等。 如果是的话,它将检查是否设置了meta.filename并将store.filename设置为在那里找到的值。 我已经提出了这个问题,以后再进行调查。

该模型

在我的特定实例中,我想将文件附加到模型。 在此示例中,我们假设我们有一个可以附加任意数量文件的应用程序(作业,贷款应用程序等)。 想想税收收据,完整的申请表以及其他扫描文件。

ApplicationSchema = new mongoose.Schema(name: Stringfiles: [ mongoose.Schema.Mixed ]
)
ApplicationSchema.methods.addFile = (file, options, fn) ->gridfs.putFile file.path, file.filename, options, (err, result) =>@files.push result@save fn

在这里,我将文件定义为混合对象类型的数组(意味着它们可以是任何东西)和方法addFile,该方法基本上采用一个至少包含路径和文件名属性的对象。 它使用它来将文件保存到gridfs并将结果的gridstore文件对象存储在files数组中(其中包含诸如id,uploadDate,contentType,名称,大小等之类的东西)。

处理要求

所有这些都插入到请求处理程序中,以处理向/ new提交的表单。 所有这一切都需要创建一个Application模型实例,从请求中添加上载的文件(在本例中,我们将文件字段命名为“ file”, 因此命名为req.files.file )并保存它。

app.post "/new", (req, res) ->application = new Application()application.name = req.body.nameopts = content_type: req.files.file.typeapplication.addFile req.files.file, opts, (err, result) ->res.redirect "/"

现在,所有这些工作的总和使我们可以非常轻松地从gridFS下载请求的文件,从而获得丰厚的回报。

app.get "/file/:id", (req, res) ->gridfs.get req.params.id, (err, file) ->res.header "Content-Type", file.typeres.header "Content-Disposition", "attachment; filename=#{file.filename}"file.stream(true).pipe(res)

在这里,我们只是通过id查找文件,并使用生成的文件对象来设置Content-Type和Content-Disposition字段,最后使用ReadableStream :: pipe将文件写出到响应对象(这是WritableStream的实例) )。 这是将数据从MongoDB流传输到客户端的魔力。

主意

这只是一个卑微的开始。 其他想法包括将gridfs完全封装在模型中。 更进一步,我们甚至可以将gridfs模型变成猫鼬插件,以允许完全黑盒使用gridfs。

随时检查该项目 ,让我知道您是否有进一步的想法。 叉开!

参考: 敏捷开发人员博客的Rant and Musings中我们的JCG合作伙伴 James Carr 从MongoDB GridFS流式传输文件

翻译自: https://www.javacodegeeks.com/2012/01/streaming-files-from-mongodb-gridfs.html

从MongoDB GridFS流式传输文件相关推荐

  1. curl上传文件linux,在Linux中如何使用curl从一个服务器流式传输文件到另一个服务器(有限的服务器资源)...

    我的API服务器具有非常有限的磁盘空间(500MB)和内存(1GB).它获得的API调用之一是接收文件.消费者调用API并传递要下载的URL. 我的服务器的"目标"是将此文件上传到 ...

  2. 读取csv文件 java_Java:逐步读取/流式传输CSV文件

    读取csv文件 java 我一直在做一些涉及读取CSV文件的工作,而我一直在使用OpenCSV ,而我的最初方法是逐行读取文件,解析内容并将其保存到地图列表中. 当文件的内容适合内存时,此方法有效,但 ...

  3. Java:逐步读取/流式传输CSV文件

    我一直在做一些涉及读取CSV文件的工作,而我一直在使用OpenCSV ,而我的最初方法是逐行读取文件,解析内容并将其保存到地图列表中. 当文件的内容适合内存时,此方法有效,但对于较大的文件来说是个问题 ...

  4. 流媒体服务器文件传输,mStream - 从任何地方流式传输音乐的个人流媒体服务器...

    mStream是一款免费的开源和跨平台个人音乐流媒体服务器,可让您在所有设备之间同步和流式传输音乐. 它由一个用NodeJS编写的轻量级音乐流媒体服务器组成; 您可以使用它将音乐从家用电脑流式传输到任 ...

  5. gstfileserver文件服务器,使用gst-rtsp-server流式传输H264文件

    请考虑我是GStreamer的初学者.我正在尝试使用gst-rtsp-server来传输记录的H264文件.所以我可以播放/暂停/寻找来自VLC播放器的视频. 这是我迄今所做的: 记录从IP摄像机的R ...

  6. 基于ASP.NET Core SignalR的流式传输

    基于ASP.NET Core SignalR的流式传输 SignalR概述 SignalR是ASP.NET Core下非常流行的实现Web实时功能的库.微软再文档中列出了适合的应用场景: 适合 Sig ...

  7. ASP.NET Core SignalR中的流式传输

    什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术. 流式传输的使用场景 有些场景中,服务器返回的数据量较大,等待时间较长,客户端不得不等待服务器返回所有数据后,再进行相应的操作.这时 ...

  8. grpc 流式传输_编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中...

    grpc 流式传输 下载各种文件(文本或二进制文件)是每个企业应用程序的生死攸关的事情. PDF文档,附件,媒体,可执行文件,CSV,超大文件等.几乎每个应用程序迟早都必须提供某种形式的下载. 下载是 ...

  9. 编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中

    下载各种文件(文本或二进制文件)是每个企业应用程序的生死攸关的事情. PDF文档,附件,媒体,可执行文件,CSV,超大文件等.几乎每个应用程序迟早都必须提供某种形式的下载. 下载是通过HTTP来实现的 ...

最新文章

  1. 在ORACLE中对存储过程加密
  2. SpringBoot如何返回页面
  3. 想要成为Java架构师不容放过的知识—Maven的版本发布
  4. Windows/Linux如何查看动态库的依赖关系?
  5. 中国数控攻牙机市场趋势报告、技术动态创新及市场预测
  6. 配置zend studio的代码格式化文件及远程单步调试
  7. Unity 导入原神人物模型
  8. Google Chrome谷歌浏览器清理缓存的常用方法
  9. 解决Win7系统无法睡眠问题
  10. 重装win10专业版系统
  11. matlab 狄利克雷函数代码,狄利克雷函数
  12. 【HTML】设置页面字体
  13. 已知两点经纬度 计算距离和方位角(MATLAB实现)
  14. Python常见数据处理技术——数据的概览与清洗、多表合并与连接、数据的汇总
  15. 拿破仑最欣赏的数学家,师从拉格朗日,撕逼泊松,一生痴迷热学最后却死于热学...
  16. DY-SV17F语音播放模块应用篇一 【IO独立模式】
  17. 软件开发流程中各版本名称(alpha/bera/RC/Release)
  18. 全国大学生软件测试开发者测试大赛笔记总结
  19. iPhone开发中的技巧整理
  20. 最详细的WordPress建站教程,什么都不会10分钟也可以

热门文章

  1. javah导出类的头文件抛出异常——java.lang.IllegalArgumentException: Not a valid class name(原因及解决方法)
  2. Mac 环境变量配置
  3. javafx 动画没效果_通过JavaFX标注制作动画效果
  4. 子类重写父类变量_为什么在子类中不重写超类的实例变量
  5. java技术专家学习路线图_向Java最佳专家的全球专家学习Java
  6. fegin 参数丢失_许多参数和丢失的信息
  7. java 性能调优_Java性能调优调查结果(第一部分)
  8. 内置对象和内置函数_内置假对象
  9. 专业QA如何实施可靠的CI / CD管道?
  10. java8 base64_Java 8中的Base64 –加入乐趣为时不晚