使用compojure从数据库提供二进制文件

Pie*_*eed 6 clojure binary-data compojure

我有以下路线定义:

(require '[compojure.core :as ccore]
         '[ring.util.response :as response])

(def *main-routes*
     (ccore/defroutes avalanche-routes
       (ccore/GET "/" [] "Hello World 2")
       (ccore/GET "/images/:id" [id] (get-image-response id))))
Run Code Online (Sandbox Code Playgroud)

在此示例中,请求/像魅力一样工作并返回预期的Hello World 2.

get-images-response方法定义如下:

(defn get-image-response
  [id]
  (let [record (db/get-image id false)]
    (-> (response/response (:data record))
        (response/content-type (:content-type record))
        (response/header "Content-Length" (:size record)))))
Run Code Online (Sandbox Code Playgroud)

虽然我得到了404,但是二进制文件的服务还没有完成.有什么想法吗?

编辑:好的,问题与正在请求图像的事实有关/images/name.jpg.一旦我删除.jpg了处理程序被调用.所以问题是如何匹配除扩展名之外的任何内容?

mty*_*aka 12

Compojure使用clout进行路由匹配.点字符在clout路线中具有特殊含义.它表示一个标记分隔符,类似于斜杠字符.以下字符在clout中都具有这个含义:/ . , ; ?.

这意味着,一个路线像"/images/:id"将不匹配的形式的URI /images/name.jpg因为images,name并且jpg每一个代表在影响力单独的令牌.

为了匹配它,您可以根据需要以多种不同方式编写路线.

如果您的所有图片都有.jpg扩展名,那么最简单的方法就是:

(GET "/images/:id.jpg" [id] ...)
Run Code Online (Sandbox Code Playgroud)

如果扩展名不同,您可以执行以下操作:

(GET "/images/:name.:extension" [name extension] ...)
Run Code Online (Sandbox Code Playgroud)

如果要限制扩展名,可以将compojure/clout传递给正则表达式:

(GET ["/images/:name.:ext", :ext #"(jpe?g|png|gif)"] [name ext] ...)
Run Code Online (Sandbox Code Playgroud)

你也可以使用通配符,它​​不太精确,并且可以匹配任何uri开头/images/:

(GET "/images/*" [*] ...)
Run Code Online (Sandbox Code Playgroud)


Pie*_*eed 5

在这种情况下,真正的答案是 clojure-couchdb 库中存在一个错误。该补丁可在 github 上找到

它归结为将 {:as :byte-array} 映射参数和值添加到通过 clj-http 发送到沙发 API 的请求中。

我的代码中的另一个问题是在ring渲染字节数组时并不真正知道如何处理它们。我没有修补环,而是将字节数组包装到java.io.ByteArrayInputStream. 这是处理下载的完整代码:

(defn get-image-response
  [id]
  (let [record (db/get-image id false)]
    (-> (response/response (new java.io.ByteArrayInputStream (:data record)))
        (response/content-type (:content-type (:content-type record)))
        (response/header "Content-Length" (:size record)))))
Run Code Online (Sandbox Code Playgroud)