blob: afd6737ac85ef9abe6d801362748f430f4553119 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
;; Copyright (c) James Reeves. All rights reserved.
;; The use and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
;; can be found in the file epl-v10.html at the root of this distribution. By
;; using this software in any fashion, you are agreeing to be bound by the
;; terms of this license. You must not remove this notice, or any other, from
;; this software.
(ns compojure.http.multipart
"Add multipart form handling to Compojure. Relies on the Apache Commons
FileUpload library."
(:use clojure.contrib.def
compojure.map-utils)
(:import [org.apache.commons.fileupload FileUpload RequestContext]
[org.apache.commons.fileupload.disk DiskFileItemFactory DiskFileItem]))
(defn multipart-form?
"Does a request have a multipart form?"
[request]
(if-let [content-type (:content-type request)]
(.startsWith content-type "multipart/form-data")))
(defvar- file-upload
(FileUpload.
(doto (DiskFileItemFactory.)
(.setSizeThreshold -1)
(.setFileCleaningTracker nil)))
"Uploader class to save multipart form values to temporary files.")
(defn- request-context
"Create a RequestContext object from a request map."
[request]
(proxy [RequestContext] []
(getContentType [] (:content-type request))
(getContentLength [] (:content-length request))
(getCharacterEncoding [] (:character-encoding request))
(getInputStream [] (:body request))))
(defn- file-map
"Create a file map from a DiskFileItem."
[#^DiskFileItem item]
{:disk-file-item item
:filename (.getName item)
:size (.getSize item)
:content-type (.getContentType item)
:tempfile (.getStoreLocation item)})
(defn parse-multipart-params
"Parse a map of multipart parameters from the request."
[request]
(reduce
(fn [param-map, #^DiskFileItem item]
(assoc-vec param-map
(keyword (.getFieldName item))
(if (.isFormField item)
(if (zero? (.getSize item))
""
(.getString item))
(file-map item))))
{}
(.parseRequest
file-upload
(request-context request))))
(defn get-multipart-params
"Retrieve multipart params from the request."
[request]
(if (multipart-form? request)
(parse-multipart-params request)
{}))
(defn with-multipart
"Decorate a Ring handler with multipart parameters."
[handler]
(fn [request]
(let [params (get-multipart-params request)
request (-> request
(assoc :multipart-params params)
(assoc :params (merge (request :params) params)))]
(handler request))))
|