Permalink
Browse files

Refactored multipart middleware, added :store option

  • Loading branch information...
1 parent b5909c9 commit dd15fa24b4a279b3e6a0496f400b55ba0e2eec36 @weavejester weavejester committed Feb 26, 2011
View
79 ring-core/src/ring/middleware/multipart_params.clj
@@ -1,27 +1,20 @@
(ns ring.middleware.multipart-params
"Parse multipart upload into params."
- (:use [ring.middleware.params :only (assoc-param)])
- (:import (org.apache.commons.fileupload
- FileUpload RequestContext)
- (org.apache.commons.fileupload.disk
- DiskFileItemFactory
- DiskFileItem)))
+ (:use [ring.middleware.params :only (assoc-param)]
+ [ring.middleware.multipart-params.byte-array :only (byte-array-store)])
+ (:import [org.apache.commons.fileupload.util Streams]
+ [org.apache.commons.fileupload
+ RequestContext
+ FileItemIterator
+ FileItemStream
+ FileUpload]))
(defn- multipart-form?
"Does a request have a multipart form?"
[request]
(if-let [^String content-type (:content-type request)]
(.startsWith content-type "multipart/form-data")))
-(def ^{:private true
- :type FileUpload
- :doc "Uploader class to save multipart form values to temporary files."}
- file-upload
- (FileUpload.
- (doto (DiskFileItemFactory.)
- (.setSizeThreshold -1)
- (.setFileCleaningTracker nil))))
-
(defn- request-context
"Create a RequestContext object from a request map."
{:tag RequestContext}
@@ -32,30 +25,36 @@
(getCharacterEncoding [this] encoding)
(getInputStream [this] (:body request))))
-(defn- file-map
- "Create a file map from a DiskFileItem."
- [^DiskFileItem item]
- (with-meta
- {:filename (.getName item)
- :size (.getSize item)
- :content-type (.getContentType item)
- :tempfile (.getStoreLocation item)}
- {:disk-file-item item}))
+(defn- file-item-iterator-seq
+ "Create a lazy seq from a FileItemIterator instance."
+ [^FileItemIterator it]
+ (lazy-seq
+ (if (.hasNext it)
+ (cons (.next it) (file-item-iterator-seq it)))))
+
+(defn- file-item-seq
+ "Create a seq of FileItem instances from a request context."
+ [context]
+ (file-item-iterator-seq
+ (.getItemIterator (FileUpload.) context)))
-(defn parse-multipart-params
+(defn- parse-file-item
+ "Parse a FileItemStream into a parameter value. If the request is a file the
+ supplied store function is used to save it."
+ [^FileItemStream item store]
+ (if (.isFormField item)
+ (Streams/asString item)
+ (store {:filename (.getName item)
+ :content-type (.getContentType item)
+ :stream (.openStream item)})))
+
+(defn- parse-multipart-params
"Parse a map of multipart parameters from the request."
- [request encoding]
- (reduce
- (fn [param-map, ^DiskFileItem item]
- (assoc-param param-map
- (.getFieldName item)
- (if (.isFormField item)
- (if (.get item) (.getString item encoding))
- (file-map item))))
- {}
- (.parseRequest
- file-upload
- (request-context request encoding))))
+ [request encoding store]
+ (into {}
+ (for [item (file-item-seq (request-context request encoding))]
+ [(.getFieldName item)
+ (parse-file-item item store)])))
(defn wrap-multipart-params
"Middleware to parse multipart parameters from a request. Adds the
@@ -65,14 +64,16 @@
Takes an optional configuration map. Recognized keys are:
:encoding - character encoding to use for multipart parsing. If not
specified, uses the request character encoding, or \"UTF-8\"
- if no request character encoding is set."
+ if no request character encoding is set.
+ :store - a function that stores a file upload. xxxx"
[handler & [opts]]
(fn [request]
(let [encoding (or (:encoding opts)
(:character-encoding request)
"UTF-8")
+ store (:store opts byte-array-store)
params (if (multipart-form? request)
- (parse-multipart-params request encoding)
+ (parse-multipart-params request encoding store)
{})
request (merge-with merge request
{:multipart-params params}
View
8 ring-core/src/ring/middleware/multipart_params/byte_array.clj
@@ -0,0 +1,8 @@
+(ns ring.middleware.multipart-params.byte-array
+ (:import org.apache.commons.io.IOUtils))
+
+(defn byte-array-store
+ "Stores multipart file parameters as an array of bytes."
+ [item]
+ (-> (select-keys item [:filename :content-type])
+ (assoc :bytes (IOUtils/toByteArray (:stream item)))))

0 comments on commit dd15fa2

Please sign in to comment.