从MongoDB GridFS流式传输文件
GridFS模塊
首先,特殊道具去tjholowaychuk誰在#node.js的IRC頻道作出回應(yīng)時(shí),我問,如果任何人有運(yùn)氣使用GridFS的從貓鼬 。 我得到的很多代碼都來自他與我分享的要旨。 無論如何,到代碼。 我將描述如何使用gridfs,并在完成基礎(chǔ)工作后說明從GridFS流式傳輸文件的過程是如此簡(jiǎn)單。
我創(chuàng)建了一個(gè)gridfs模塊,該模塊基本上通過mongoose(我在整個(gè)應(yīng)用程序中使用)訪問GridStore,該模塊還可以共享將mongoose連接到mongodb服務(wù)器時(shí)創(chuàng)建的數(shù)據(jù)庫連接。
mongoose = require "mongoose" request = require "request"GridStore = mongoose.mongo.GridStore Grid = mongoose.mongo.Grid ObjectID = mongoose.mongo.BSONPure.ObjectID如果我們不能在mongodb中添加任何文件,我們將無法獲取文件,因此讓我們創(chuàng)建一個(gè)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實(shí)際上,這只是委托給GridStore中存在的putFile操作(作為mongodb模塊的一部分)。 我也有一些邏輯來解析選項(xiàng),如果沒有提供默認(rèn)值,則提供默認(rèn)值。 要注意的一個(gè)有趣功能是,我將文件名存儲(chǔ)在元數(shù)據(jù)中,因?yàn)楫?dāng)時(shí)我遇到了一個(gè)有趣的問題,即從gridFS檢索的文件將id作為文件名(即使在mongo中查看發(fā)現(xiàn)文件名實(shí)際上是在數(shù)據(jù)庫)。
現(xiàn)在進(jìn)行g(shù)et操作。 此方法的原始實(shí)現(xiàn)只是通過調(diào)用store.readBuffer()將內(nèi)容作為緩沖區(qū)傳遞給所提供的回調(diào),但是現(xiàn)在已更改為將結(jié)果存儲(chǔ)對(duì)象傳遞給回調(diào)。 其值是調(diào)用者可以使用商店對(duì)象來訪問元數(shù)據(jù),contentType和其他詳細(xì)信息。 用戶還可以確定他們想如何讀取文件(進(jìn)入內(nèi)存還是使用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這段代碼有一個(gè)小問題,它檢查文件名和fileId是否相等。 如果是的話,它將檢查是否設(shè)置了meta.filename并將store.filename設(shè)置為在那里找到的值。 我已經(jīng)提出了這個(gè)問題,以后再進(jìn)行調(diào)查。
該模型
在我的特定實(shí)例中,我想將文件附加到模型。 在此示例中,我們假設(shè)我們有一個(gè)可以附加任意數(shù)量文件的應(yīng)用程序(作業(yè),貸款應(yīng)用程序等)。 想想稅收收據(jù),完整的申請(qǐng)表以及其他掃描文件。
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在這里,我將文件定義為混合對(duì)象類型的數(shù)組(意味著它們可以是任何東西)和方法addFile,該方法基本上采用一個(gè)至少包含路徑和文件名屬性的對(duì)象。 它使用它來將文件保存到gridfs并將結(jié)果的gridstore文件對(duì)象存儲(chǔ)在files數(shù)組中(其中包含諸如id,uploadDate,contentType,名稱,大小等之類的東西)。
處理要求
所有這些都插入到請(qǐng)求處理程序中,以處理向/ new提交的表單。 所有這一切都需要?jiǎng)?chuàng)建一個(gè)Application模型實(shí)例,從請(qǐng)求中添加上載的文件(在本例中,我們將文件字段命名為“ 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 "/"現(xiàn)在,所有這些工作的總和使我們可以非常輕松地從gridFS下載請(qǐng)求的文件,從而獲得豐厚的回報(bào)。
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查找文件,并使用生成的文件對(duì)象來設(shè)置Content-Type和Content-Disposition字段,最后使用ReadableStream :: pipe將文件寫出到響應(yīng)對(duì)象(這是WritableStream的實(shí)例) )。 這是將數(shù)據(jù)從MongoDB流傳輸?shù)娇蛻舳说哪ЯΑ?
主意
這只是一個(gè)卑微的開始。 其他想法包括將gridfs完全封裝在模型中。 更進(jìn)一步,我們甚至可以將gridfs模型變成貓鼬插件,以允許完全黑盒使用gridfs。
隨時(shí)檢查該項(xiàng)目 ,讓我知道您是否有進(jìn)一步的想法。 叉開!
參考: 敏捷開發(fā)人員博客的Rant and Musings中我們的JCG合作伙伴 James Carr 從MongoDB GridFS流式傳輸文件
翻譯自: https://www.javacodegeeks.com/2012/01/streaming-files-from-mongodb-gridfs.html
總結(jié)
以上是生活随笔為你收集整理的从MongoDB GridFS流式传输文件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑主机主板漏电开不了机(电脑主板漏电开
- 下一篇: 如果–否则为编码风格最佳实践