|
10 | 10 | (:require [ring.util.codec :refer [assoc-conj]]
|
11 | 11 | [ring.util.request :as req]
|
12 | 12 | [ring.util.parsing :as parsing])
|
13 |
| - (:import [org.apache.commons.fileupload UploadContext |
14 |
| - FileItemIterator |
15 |
| - FileItemStream |
16 |
| - FileUpload |
17 |
| - ProgressListener] |
| 13 | + (:import [org.apache.commons.fileupload |
| 14 | + UploadContext |
| 15 | + FileItemIterator |
| 16 | + FileItemStream |
| 17 | + FileUpload |
| 18 | + ProgressListener] |
18 | 19 | [org.apache.commons.io IOUtils]))
|
19 |
| -(defn- progress-listener |
20 |
| - "Create a progress listener that calls the supplied function." |
21 |
| - [request progress-fn] |
| 20 | + |
| 21 | +(defn- progress-listener [request progress-fn] |
22 | 22 | (reify ProgressListener
|
23 |
| - (update [this bytes-read content-length item-count] |
| 23 | + (update [_ bytes-read content-length item-count] |
24 | 24 | (progress-fn request bytes-read content-length item-count))))
|
25 | 25 |
|
26 |
| -(defn- multipart-form? |
27 |
| - "Does a request have a multipart form?" |
28 |
| - [request] |
| 26 | +(defn- set-progress-listener [^FileUpload upload request progress-fn] |
| 27 | + (when progress-fn |
| 28 | + (.setProgressListener upload (progress-listener request progress-fn)))) |
| 29 | + |
| 30 | +(defn- file-upload [request {:keys [progress-fn max-file-size]}] |
| 31 | + (doto (FileUpload.) |
| 32 | + (.setFileSizeMax (or max-file-size -1)) |
| 33 | + (set-progress-listener request progress-fn))) |
| 34 | + |
| 35 | +(defn- multipart-form? [request] |
29 | 36 | (= (req/content-type request) "multipart/form-data"))
|
30 | 37 |
|
31 |
| -(defn- request-context |
32 |
| - "Create an UploadContext object from a request map." |
33 |
| - {:tag UploadContext} |
34 |
| - [request encoding] |
| 38 | +(defn- request-context ^UploadContext [request encoding] |
35 | 39 | (reify UploadContext
|
36 |
| - (getContentType [this] (get-in request [:headers "content-type"])) |
37 |
| - (getContentLength [this] (or (req/content-length request) -1)) |
38 |
| - (contentLength [this] (or (req/content-length request) -1)) |
39 |
| - (getCharacterEncoding [this] encoding) |
40 |
| - (getInputStream [this] (:body request)))) |
41 |
| - |
42 |
| -(defn- file-item-iterator-seq |
43 |
| - "Create a lazy seq from a FileItemIterator instance." |
44 |
| - [^FileItemIterator it] |
| 40 | + (getContentType [_] (get-in request [:headers "content-type"])) |
| 41 | + (getContentLength [_] (or (req/content-length request) -1)) |
| 42 | + (contentLength [_] (or (req/content-length request) -1)) |
| 43 | + (getCharacterEncoding [_] encoding) |
| 44 | + (getInputStream [_] (:body request)))) |
| 45 | + |
| 46 | +(defn- file-item-iterator-seq [^FileItemIterator it] |
45 | 47 | (lazy-seq
|
46 |
| - (if (.hasNext it) |
| 48 | + (when (.hasNext it) |
47 | 49 | (cons (.next it) (file-item-iterator-seq it)))))
|
48 | 50 |
|
49 | 51 | (defn- file-item-seq [^FileUpload upload context]
|
|
66 | 68 | fallback-encoding)))
|
67 | 69 | v)])))
|
68 | 70 |
|
69 |
| -(defn- parse-file-item |
70 |
| - "Parse a FileItemStream into a key-value pair. If the request is a file the |
71 |
| - supplied store function is used to save it." |
72 |
| - [^FileItemStream item store] |
| 71 | +(defn- parse-file-item [^FileItemStream item store] |
73 | 72 | [(.getFieldName item)
|
74 | 73 | (if (.isFormField item)
|
75 | 74 | {:bytes (IOUtils/toByteArray (.openStream item))
|
|
79 | 78 | :stream (.openStream item)}))
|
80 | 79 | (.isFormField item)])
|
81 | 80 |
|
82 |
| -(defn- make-file-upload [request {:keys [progress-fn max-file-size]}] |
83 |
| - (let [upload (FileUpload.)] |
84 |
| - (.setFileSizeMax upload (or max-file-size -1)) |
85 |
| - (when progress-fn |
86 |
| - (.setProgressListener upload (progress-listener request progress-fn))) |
87 |
| - upload)) |
88 |
| - |
89 |
| -(defn- load-var |
90 |
| - "Returns the var named by the supplied symbol, or nil if not found. Attempts |
91 |
| - to load the var namespace on the fly if not already loaded." |
92 |
| - [sym] |
| 81 | +(defn- load-var [sym] |
93 | 82 | (require (symbol (namespace sym)))
|
94 | 83 | (find-var sym))
|
95 | 84 |
|
|
100 | 89 | (func))))
|
101 | 90 |
|
102 | 91 | (defn- parse-multipart-params
|
103 |
| - "Parse a map of multipart parameters from the request." |
104 | 92 | [request {:keys [encoding fallback-encoding store] :as options}]
|
105 | 93 | (let [store (or store @default-store)
|
106 | 94 | fallback-encoding (or encoding
|
107 | 95 | fallback-encoding
|
108 | 96 | (req/character-encoding request)
|
109 | 97 | "UTF-8")]
|
110 | 98 | (->> (request-context request fallback-encoding)
|
111 |
| - (file-item-seq (make-file-upload request options)) |
| 99 | + (file-item-seq (file-upload request options)) |
112 | 100 | (map #(parse-file-item % store))
|
113 | 101 | (decode-string-values fallback-encoding encoding)
|
114 | 102 | (reduce (fn [m [k v]] (assoc-conj m k v)) {}))))
|
|
0 commit comments