Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
File upload example in Compojure
(ns fileupload.core
(:use [net.cgrand.enlive-html
:only [deftemplate defsnippet content clone-for
nth-of-type first-child do-> set-attr sniptest at emit*]]
(:require (compojure [route :as route])
(ring.util [response :as response])
(ring.middleware [multipart-params :as mp])
(clojure.contrib [duck-streams :as ds]))
(defn render [t]
(apply str t))
(deftemplate index "fileupload/index.html" [])
(deftemplate upload-success "fileupload/success.html" [])
(defn upload-file
(ds/copy (file :tempfile) (ds/file-str "file.out"))
(render (upload-success)))
(defroutes public-routes
(GET "/" [] (render (index)))
(POST "/file" {params :params} (upload-file (get params "file")))))
(defn start-app []
(future (run-jetty (var public-routes) {:port 8000})))
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8" />
<title>Compojure file upload</title>
<form action="/file" method="post" enctype="multipart/form-data">
<input name="file" type="file" size="20" />
<input type="submit" name="submit" value="submit" />
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8" />
<title>Compojure file upload</title>
<h1>File upload successful!</h1>

nikolaplejic commented Sep 2, 2010

Leiningen project file:

(defproject fileupload "1.0.0-SNAPSHOT"
  :description "a file upload example"
  :dependencies [[org.clojure/clojure "1.2.0-beta1"]
                 [org.clojure/clojure-contrib "1.2.0-beta1"]
                 [compojure "0.4.1"]
                 [enlive "1.0.0-SNAPSHOT"]
                 [ring/ring-jetty-adapter "0.2.5"]
                 [ring/ring-devel "0.2.5"]]) 

Thanks for this, I've updated the lib versions and made it a project for future gigs.



eggsby commented Jan 29, 2014

As of Jan 2014 this is incredibly outdated.

laliluna commented Feb 7, 2014

I disagree. The basic concept still works. Here a simplified version of the copying

(POST "/fileupload" {:keys [params]}
(let [{:keys [tempfile filename]} (get params "file")]
   (io/copy tempfile ( (str root-directory "/" filename)))) 
   (response "OK")))

I found compojure already wrap-multipart-params, so no need to wrap it again.
Below code works for me

  (POST "/filestorage" 
        {{{tempfile :tempfile filename :filename} :img} :params :as params}
        (io/copy tempfile (io/file filename)))

pcwerk commented Aug 25, 2014

@wewetom, your example looks promising. How about handling multiple files?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment