Reputation: 21
When I try to extract the multipart-params from a POST request like this:
(defroutes upload-routes
(POST "/upload" {params :params} (println params))
I got {}
.
Then I tried like this:
(defroutes upload-routes
(POST "/upload" {multipart-params :multipart-params} (println multipart-params))
I still got {}
.
I guess there are something wrong about my middleware.
So I tried to change the handler, here are the handlers I had tried:
(ns cloudserver.handler
(:require [compojure.core :refer [defroutes routes]]
[compojure.route :as route]
[compojure.handler :as handler]
[cloudserver.routes.home :refer [home-routes]]
[noir.util.middleware :as noir-middleware]
[cloudserver.routes.auth :refer [auth-routes]]
[cloudserver.routes.upload :refer [upload-routes]]
[cloudserver.routes.search :refer [search-routes]]
[cloudserver.routes.download :refer [download-routes]]
[ring.middleware.defaults :refer [api-defaults wrap-defaults site-defaults]]
[ring.middleware.multipart-params :refer [wrap-multipart-params]]
[ring.middleware.params :refer [wrap-params]]
[noir.session :as session]
[ring.middleware.session.memory :refer [memory-store]]))
(def app
(->
(routes auth-routes
home-routes
upload-routes
search-routes
download-routes
app-routes)
session/wrap-noir-session
(wrap-defaults(assoc-in site-defaults [:security :anti-forgery] false)
wrap-multipart-params
wrap-params))
(def app
(->
(routes auth-routes
home-routes
upload-routes
search-routes
download-routes
app-routes)
session/wrap-noir-session
(wrap-defaults(assoc-in site-defaults [:security :anti-forgery] false)
wrap-multipart-params))
(def app
(->
(routes auth-routes
home-routes
upload-routes
search-routes
download-routes
app-routes)
session/wrap-noir-session
(wrap-defaults (-> site-defaults
(assoc-in [:security :anti-forgery] false)
(assoc-in [:params :multipart] true)
(assoc-in [:params :nested] true)))
handler/site))
(def app
(->
(routes auth-routes
home-routes
upload-routes
search-routes
download-routes
app-routes)
wrap-multipart-params
session/wrap-noir-session
(wrap-defaults(assoc-in site-defaults [:security :anti-forgery] false)))
(def app
(noir-middleware/app-handler
[auth-routes
home-routes
upload-routes
search-routes
download-routes
app-routes]
:ring-defaults (assoc site-defaults :security nil)))
But the only result I got is {}
My client code is:
public int upload (String filename, String[] tags, String time, String fingerprint) throws IOException {
String url = host + "/upload";
CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
HttpPost httpPost = new HttpPost(url);
MultipartEntityBuilder mulentity = MultipartEntityBuilder.create();
mulentity.addBinaryBody("photo", new File(filename));
for (int i = 0; i < tags.length; i ++) {
mulentity.addTextBody("tag" + i, tags[i]);
}
mulentity.addTextBody("fingerprint", fingerprint);
mulentity.addTextBody("time", time);
mulentity.addTextBody("filename", filename.substring(filename.lastIndexOf(File.separatorChar) + 1, filename.length()));
HttpEntity entity = mulentity.build();
httpPost.setEntity(entity);
httpPost.setHeader("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
int status = 3;
try {
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = httpClient.execute(httpPost, responseHandler);
status = Integer.parseInt(response);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
httpClient.close();
}
return status;
}
I am really a green hand in clojure web programming. Thanks a lot!
Problem sovled. It's because the boundary in the request is wrong.
Upvotes: 2
Views: 665
Reputation: 11130
I too am "Clojure Green", but in my multipart Ring + Compojure API app, I just destructure the request on the names of the parameters that come in on the multipart request. The one that is actually a temp file gets output by the printf below has a string representation like "#object[java.io.File 0x4blahblahblah". The middleware took care of lifting it out of the request map and making the parameters available by just their names, I think.
(defroutes upload-routes
(POST "/upload" [photo tag fingerprint time filename :as request]
(printf
"photo %s, tag %s, fingerprint %s, time %s, filename %s"
photo tag fingerprint time filename)))
The :as request isn't really needed if you're not going to do anything with the whole request map. If all you are doing is printf...maybe include it in the printf and you'll get to see a little how the sausage gets made in Ring. Its Maps all the way down.
Upvotes: 2