File upload in Clojure & Compojure
2010-09-02 in clojure
Compojure is coming to be a really nice framework which is, together with the excellent Enlive templating/transformation library, enough to make this Lisp n00b take a shot at developing a toy project or two in a Lisp dialect. I struggled a bit today to do a file upload: it’s a relatively recent feature in the framework and although it’s pretty straightforward, it took me a while to get it up to speed. Here’s a really basic and primitive example which assumes you have clojure.contrib, Ring, Compojure and Enlive installed.
The key step is to wrap your upload handling route with the wrap-multipart-params
middleware from the ring.middleware.multipart-params
namespace. The route responsible for the file upload is the latter one:
(defroutes public-routes
(GET "/" [] (render (index)))
(mp/wrap-multipart-params
(POST "/file" {params :params} (upload-file (get params "file")))))
(file
in the (get params "file")
call is the name of the input
field.)
Next, here’s the upload-file
handler function called by the route which just takes the file and copies it to a file named file.out
in the current project directory:
(defn upload-file
[file]
(ds/copy (file :tempfile) (ds/file-str "file.out"))
(render (upload-success)))
(ds
is an alias for the clojure.contrib.duck-streams
namespace, and render
is a function which takes a template and returns its string representation. upload-success
is an Enlive template.)
Voila! Not hard at all. Also check out the gist with complete code and template files.