2015-10-27 60 views
0

我有一個使用Clojure,Clojurescript和Monger的網絡應用程序。文件通過GridFS上傳並存儲在Mongo中。可以請求下載相同的文件;目前這是通過將文件寫入(服務器)磁盤並將其作爲靜態文件來完成的,但這有點尷尬;我如何直接在Clojure/Java中提供由GridFS對象表示的文件?路由由Ring/Compojure處理。如何在Clojure/Monger中將GridFS文件流到Web客戶端?

回答

2

事實證明,Luminus中使用的Ring/Compojure基礎結構能夠返回輸出流,從而在不觸碰驅動器的情況下輕鬆傳輸文件。

(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))) 
相關問題