|
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