代码之家  ›  专栏  ›  技术社区  ›  Pieter Breed

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

  •  5
  • Pieter Breed  · 技术社区  · 14 年前

    我有以下路由定义:

    (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))))
    

    在本例中,请求 / 像个魔咒一样工作,回报预期的 Hello World 2 .

    get images响应方法的定义如下:

    (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)))))
    

    但是我得到了404,所以二进制文件的服务还没有完全起作用。有什么想法吗?

    编辑: 好的,这个问题与图像被请求的事实有关 /images/name.jpg . 一旦我移除 .jpg 处理程序被调用。所以问题变成了,除了扩展名之外,我如何匹配其他内容?

    2 回复  |  直到 14 年前
        1
  •  11
  •   mtyaka    14 年前

    组件使用 clout 用于路由匹配。点状字符在影响力路线中有着特殊的意义。它表示一个标记分隔符,类似于斜杠字符。以下字符在“影响力”中均具有此含义: / . , ; ? .

    这意味着像 "/images/:id" 与表单的URI不匹配 /images/name.jpg 自从 images , name jpg 每一个都代表着影响力中的一个单独的象征。

    为了匹配它,您可以根据需要以多种不同的方式组成您的路线。

    如果你所有的图像都有 .jpg 扩展,最简单的事情是:

    (GET "/images/:id.jpg" [id] ...)
    

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

    (GET "/images/:name.:extension" [name extension] ...)
    

    如果要限制扩展,可以传递一个正则表达式compojeure/clout:

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

    您还可以使用通配符,它的精度较低,可以匹配以开头的任何URI。 /images/ :

    (GET "/images/*" [*] ...)
    
        2
  •  4
  •   Pieter Breed    14 年前

    在这个案例中,真正的答案是clojure couchdb库中有一个bug。补丁可用 on github here .

    它归根结底是将:as:byte array map参数和值添加到通过CLJ HTTP发送到coach的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)))))