Skip to content

Commit dd36e21

Browse files
committed
Rewritten multipart library to use ServletFileUpload courtesy of Adam
Blinkinsop
2 parents e365932 + 1e5ab06 commit dd36e21

1 file changed

Lines changed: 18 additions & 58 deletions

File tree

src/compojure/http/multipart.clj

Lines changed: 18 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,78 +5,38 @@
55
;; using this software in any fashion, you are agreeing to be bound by the
66
;; terms of this license. You must not remove this notice, or any other, from
77
;; this software.
8+
;; Modified by Adam Blinkinsop <blinks@acm.org> in August 2009.
89

910
(ns compojure.http.multipart
1011
"Add multipart form handling to Compojure. Relies on the Apache Commons
1112
FileUpload library."
1213
(:use clojure.contrib.def)
1314
(:use compojure.map-utils)
14-
(:import org.apache.commons.fileupload.FileUpload)
15-
(:import org.apache.commons.fileupload.RequestContext)
16-
(:import org.apache.commons.fileupload.disk.DiskFileItemFactory)
17-
(:import org.apache.commons.fileupload.disk.DiskFileItem))
15+
(:import [org.apache.commons.fileupload.servlet ServletFileUpload]))
1816

19-
(defn multipart-form?
20-
"Does a request have a multipart form?"
17+
(defn multipart?
18+
"Does this request contain multipart content?"
2119
[request]
22-
(if-let [content-type (:content-type request)]
23-
(.startsWith content-type "multipart/form-data")))
20+
(ServletFileUpload/isMultipartContent request))
2421

25-
(defvar- file-upload
26-
(FileUpload.
27-
(doto (DiskFileItemFactory.)
28-
(.setSizeThreshold -1)
29-
(.setFileCleaningTracker nil)))
30-
"Uploader class to save multipart form values to temporary files.")
22+
(defvar- upload (ServletFileUpload.))
3123

32-
(defn- request-context
33-
"Create a RequestContext object from a request map."
34-
[request]
35-
(proxy [RequestContext] []
36-
(getContentType [] (:content-type request))
37-
(getContentLength [] (:content-length request))
38-
(getCharacterEncoding [] (:character-encoding request))
39-
(getInputStream [] (:body request))))
40-
41-
(defn- file-map
42-
"Create a file map from a DiskFileItem."
43-
[#^DiskFileItem item]
44-
{:disk-file-item item
45-
:filename (.getName item)
46-
:size (.getSize item)
47-
:content-type (.getContentType item)
48-
:tempfile (.getStoreLocation item)})
49-
50-
(defn parse-multipart-params
51-
"Parse a map of multipart parameters from the request."
52-
[request]
53-
(reduce
54-
(fn [param-map, #^DiskFileItem item]
55-
(assoc-vec param-map
56-
(keyword (.getFieldName item))
57-
(if (.isFormField item)
58-
(if (zero? (.getSize item))
59-
""
60-
(.getString item))
61-
(file-map item))))
62-
{}
63-
(.parseRequest
64-
file-upload
65-
(request-context request))))
24+
(defn field-seq
25+
"Map field names to values, which will either be a simple string or map.
6626
67-
(defn get-multipart-params
68-
"Retrieve multipart params from the request."
27+
Multipart values will be maps with content-type, name (original filename),
28+
and stream (an open input stream object)."
6929
[request]
70-
(if (multipart-form? request)
71-
(parse-multipart-params request)
72-
{}))
30+
(map (fn [i] {(keyword (.getFieldName i))
31+
(if (.isFormField i)
32+
(.getParameter request (.getFieldName i))
33+
{:content-type (.getContentType i)
34+
:name (.getName i)
35+
:stream (.openStream i)})})
36+
(.getItemIterator upload request)))
7337

7438
(defn with-multipart
75-
"Decorate a Ring handler with multipart parameters."
7639
[handler]
7740
(fn [request]
78-
(let [params (get-multipart-params request)
79-
request (-> request
80-
(assoc :multipart-params params)
81-
(assoc :params (merge (request :params) params)))]
41+
(let [req (merge request {:params (merge (field-seq request))})]
8242
(handler request))))

0 commit comments

Comments
 (0)