2017-09-05 5 views
2

Cela fait deux jours que je me bats avec ça et je ne trouve pas de solution.Problème Compojure affichant une image

Donc tout ce que je suis en train de faire est d'afficher une image dans le navigateur, mais quand je fais appel le point final c'est ce qui se passe:

Cannot JSON encode object of class: class java.io.File 

Endpoint

(context "/servers" [] 
      :datomic true 

      (GET "/:id/graph/:panel-type" {db :db user :user} 
       :summary "Return a server graph image" 
       :path-params [id :- Long 
           panel-type :- String] 
       (let [file-path (str panel-type ".png") 

         result (-> (response/response (clojure.java.io/file file-path)) 
           (response/content-type "image/png")))] 

        (ok result)))) ;; ring.util.http-response 

I Je suis nouveau sur l'API compojure, mais quelque chose me fait penser qu'il y a un problème avec l'implémentation de middleware - des formats personnalisés?

Middleware

(defn wrap-formats [handler] 
    (let [wrapped (wrap-restful-format 
        handler 
        {:formats [:json-kw :transit-json :transit-msgpack]})] 
    (fn [request] 
     ;; disable wrap-formats for websockets 
     ;; since they're not compatible with this middleware 
     ((if (:websocket? request) handler wrapped) request)))) 

Stacktrace

com.fasterxml.jackson.core.JsonGenerationException: Cannot JSON encode object of class: class java.io.File: cpu.png 
at cheshire.generate$generate.invokeStatic(generate.clj:152) 
at cheshire.generate$generate.invoke(generate.clj:116) 
at cheshire.generate$generate.invokeStatic(generate.clj:122) 
at cheshire.generate$generate.invoke(generate.clj:116) 
at cheshire.core$generate_string.invokeStatic(core.clj:74) 
at cheshire.core$generate_string.invoke(core.clj:49) 
at ring.middleware.format_response$make_json_encoder$fn__20198.invoke(format_response.clj:221) 
at ring.middleware.format_response$wrap_format_response$fn__20186.invoke(format_response.clj:204) 
at ring.middleware.keyword_params$wrap_keyword_params$fn__4302.invoke(keyword_params.clj:36) 
at ring.middleware.nested_params$wrap_nested_params$fn__20350.invoke(nested_params.clj:89) 
at ring.middleware.params$wrap_params$fn__4376.invoke(params.clj:67) 
at compojure.api.middleware$wrap_options$fn__23551.invoke(middleware.clj:74) 
at compojure.api.routes.Route.invoke(routes.clj:74) 
at clojure.lang.Var.invoke(Var.java:381) 
at compojure.core$routing$fn__4157.invoke(core.clj:185) 
at clojure.core$some.invokeStatic(core.clj:2674) 
at clojure.core$some.invoke(core.clj:2665) 
at compojure.core$routing.invokeStatic(core.clj:185) 
at compojure.core$routing.doInvoke(core.clj:182) 
at clojure.lang.RestFn.applyTo(RestFn.java:139) 
at clojure.core$apply.invokeStatic(core.clj:659) 
at clojure.core$apply.invoke(core.clj:652) 
at compojure.core$routes$fn__4161.invoke(core.clj:192) 
at clojure.lang.Var.invoke(Var.java:381) 
at ring.middleware.reload$wrap_reload$fn__46696.invoke(reload.clj:39) 
at selmer.middleware$wrap_error_page$fn__46709.invoke(middleware.clj:9) 
at prone.middleware$wrap_exceptions$fn__46879.invoke(middleware.clj:126) 
at buddy.auth.middleware$wrap_authentication$fn__44919.invoke(middleware.clj:42) 
at buddy.auth.middleware$wrap_authorization$fn__44927.invoke(middleware.clj:94) 
at ring.middleware.cors$handle_cors.invokeStatic(cors.clj:146) 
at ring.middleware.cors$handle_cors.invoke(cors.clj:135) 
at ring.middleware.cors$wrap_cors$fn__45217.invoke(cors.clj:160) 
at ring.middleware.flash$wrap_flash$fn__45283.invoke(flash.clj:39) 
at ring.middleware.session$wrap_session$fn__45465.invoke(session.clj:108) 
at ring.middleware.keyword_params$wrap_keyword_params$fn__4302.invoke(keyword_params.clj:36) 
at ring.middleware.nested_params$wrap_nested_params$fn__20350.invoke(nested_params.clj:89) 
at ring.middleware.multipart_params$wrap_multipart_params$fn__45551.invoke(multipart_params.clj:172) 
at ring.middleware.params$wrap_params$fn__4376.invoke(params.clj:67) 
at ring.middleware.cookies$wrap_cookies$fn__45416.invoke(cookies.clj:175) 
at ring.middleware.absolute_redirects$wrap_absolute_redirects$fn__45638.invoke(absolute_redirects.clj:47) 
at ring.middleware.resource$wrap_resource$fn__45567.invoke(resource.clj:37) 
at ring.middleware.content_type$wrap_content_type$fn__25387.invoke(content_type.clj:34) 
at ring.middleware.default_charset$wrap_default_charset$fn__45610.invoke(default_charset.clj:31) 
at ring.middleware.not_modified$wrap_not_modified$fn__25417.invoke(not_modified.clj:53) 
at ring.middleware.x_headers$wrap_x_header$fn__45246.invoke(x_headers.clj:22) 
at ring.middleware.x_headers$wrap_x_header$fn__45246.invoke(x_headers.clj:22) 
at ring.middleware.x_headers$wrap_x_header$fn__45246.invoke(x_headers.clj:22) 
at voltage.middleware$wrap_bearer_token$fn__46930.invoke(middleware.clj:72) 
at ring.middleware.webjars$wrap_webjars$fn__45738.invoke(webjars.clj:40) 
at voltage.middleware$wrap_internal_error$fn__46919.invoke(middleware.clj:37) 
at immutant.web.internal.undertow$create_http_handler$reify__57634.handleRequest(undertow.clj:239) 
at org.projectodd.wunderboss.web.undertow.async.websocket.UndertowWebsocket$2.handleRequest(UndertowWebsocket.java:107) 
at io.undertow.server.session.SessionAttachmentHandler.handleRequest(SessionAttachmentHandler.java:68) 
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) 
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:802) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:745) 

Toute idée de ce qui précède est très apprécié.

Répondre

3

Le problème est que vous appelez à la fois ring.util.response/response et ring.util.http-response/ok:

(ok (ring.util.response/response "foo")) 
=> {:status 200, :headers {}, :body {:status 200, :headers {}, :body "foo"}} 

En utilisant l'un d'eux fonctionne séparément:

(ns compojure.api.examples.handler 
    (:require [clojure.java.io :as io] 
      [compojure.api.sweet :refer :all] 
      [ring.middleware.format :refer [wrap-restful-format]] 
      [ring.util.http-response :refer :all] 
      [ring.util.response :as response] 
      [compojure.api.examples.domain :refer :all] 
      [schema.core :as s])) 

(defn wrap-formats [handler] 
    (let [wrapped (wrap-restful-format 
        handler 
        {:formats [:json-kw :transit-json :transit-msgpack]})] 
    (fn [request] 
     ;; disable wrap-formats for websockets 
     ;; since they're not compatible with this middleware 
     ((if (:websocket? request) handler wrapped) request)))) 

(def app 
    (wrap-formats 
    (api 
    (GET "/lisplogo" [] 
     (-> (response/response (io/file "lisplogo_256.png")) 
      (response/content-type "image/png"))) 

    (GET "/lisplogo2" [] 
     (assoc-in (ok (io/file "lisplogo_256.png")) 
        [:headers "Content-Type"] 
        "image/png"))))) 
+0

Vous êtes, bien sûr! Regardé la source (ok) et figuré que 2 minutes avant votre réponse ... Merci! – Sasha

0

Si vous voulez affichage image, un meilleur retour page HTML avec <img> lié à votre répertoire avec des actifs statiques (généralement resources/).

Si vous voulez télécharger fichier, voici un exemple de gestionnaire Compojure-api:

(ns example.app 
    (:require [clojure.java.io :as io] 
      [ring.util.response :as r])) 

(defn file-download [name] 
    (let [filename (str "resources/" name) 
     bin (io/file filename)] 
    (-> (r/response (io/input-stream bin)) 
     (r/header "Content-Type" "application/octet-stream") 
     (r/header "Content-Disposition" "attachment") 
     (r/header "Content-Length" (.length bin)) 
     (r/status 200)))) 

adapter et utiliser cette fonction en place où votre let va dans endpoint, espérons qu'il aide.