如何在Clojure/Monger中将GridFS文件流式传输到web客户端



我有一个使用Clojure、Clojuescrapt和Monger的web应用程序。文档通过GridFS上传并存储在Mongo中。可以请求下载相同的文件;目前,这是通过将文件写入(服务器的)磁盘并将其作为静态文件来实现的,但这有点尴尬;如何在Clojure/Java中直接为GridFS对象表示的文件提供服务?路由由Ring/Composjure处理。

事实证明,Luminus中使用的Ring/Composjure基础设施能够返回输出流,从而在不接触驱动器的情况下轻松传输文件。

(ns my-app.routes.updown
  "File uploading and insertion into database"
  (:use compojure.core)
  (:require [my-app.db.core :as db] ;; all the db functions you see here are just wrappers for the Monger functions you'd expect
            [ring.util.response :as r]
            [ring.util.io :as io]))
(defn make-file-stream
  "Takes an input stream--such as a MongoDBObject stream--and streams it"
  [file]  
  (io/piped-input-stream
   (fn [output-stream]
       (.writeTo file output-stream))))
(defn download-file-by-id "Downloads the requested file, if privileges are allowed"
  [id-string]
  (let [mongo-file (db/find-file-by-id id-string)
        file-map (db/map-from-mongo-obj mongo-file)
        content-type (-> file-map :metadata :contentType)
        file-name (-> file-map :filename)]
        (-> mongo-file
            make-file-stream
            r/response
            (#(r/header % "Content-Disposition" ; to get the right default file-name
                        (str "attachment; filename="" file-name """)))
        (#(r/header % "Content-Type" content-type))))) ; final wrapper: offer the right "open with" dialogue

;; this is called by my main routes def like so:
;; (notice no extra wrappers needed, as wrapping took place in download-file-by-id)
;; (defroutes home-routes
;;     (GET "/files/:id-string" [id-string]
;;        (up/download-file-by-id id-string)))

相关内容

  • 没有找到相关文章

最新更新