Skip to content

Instantly share code, notes, and snippets.

@nikolaplejic
Created September 2, 2010 17:54
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save nikolaplejic/562624 to your computer and use it in GitHub Desktop.
Save nikolaplejic/562624 to your computer and use it in GitHub Desktop.
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*]]
[compojure.core]
[ring.adapter.jetty])
(:require (compojure [route :as route])
(ring.util [response :as response])
(ring.middleware [multipart-params :as mp])
(clojure.contrib [duck-streams :as ds]))
(:gen-class))
(defn render [t]
(apply str t))
(deftemplate index "fileupload/index.html" [])
(deftemplate upload-success "fileupload/success.html" [])
(defn upload-file
[file]
(ds/copy (file :tempfile) (ds/file-str "file.out"))
(render (upload-success)))
(defroutes public-routes
(GET "/" [] (render (index)))
(mp/wrap-multipart-params
(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">
<head>
<meta charset="UTF-8" />
<title>Compojure file upload</title>
</head>
<body>
<form action="/file" method="post" enctype="multipart/form-data">
<input name="file" type="file" size="20" />
<input type="submit" name="submit" value="submit" />
</form>
</body>
</html>
(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"]])
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Compojure file upload</title>
</head>
<body>
<h1>File upload successful!</h1>
</body>
</html>
@nikolaplejic
Copy link
Author

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"]]) 

@dfuenzalida
Copy link

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

https://github.com/dfuenzalida/compojure-file-upload

Cheers,

Denis

@darkone23
Copy link

As of Jan 2014 this is incredibly outdated.

@laliluna
Copy link

laliluna commented Feb 7, 2014

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

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

@sniperliu
Copy link

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

@jinwei233
Copy link

@pcwerk
Copy link

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