ring-clojure/ring

wrap-multipart-params middleware not showing any params in :multipart-params

Closed this issue · 5 comments

I am receiving multipart params that contain a file in my handler function in the server:

(defn upload-shot-video [req]
  (prn "uploading video")

  (prn "video is " (-> req :params))
  (prn "video is " (-> req :body))
  (clojure.java.io/copy (-> req :body) (clojure.java.io/file "./resources/public/video.mov"))

  (let [filename (str (rand-str 100) ".mov")]
    (s3/put-object
     :bucket-name "humboi-videos"
     :key filename
     :file "./resources/public/video.mov"
     :access-control-list {:grant-permission ["AllUsers" "Read"]})
    (db/add-video {:name (-> req :params :name)
                   :uri (str "https://humboi-videos.s3-us-west-1.amazonaws.com/" filename)}))
  (r/response {:res "okay!"}))

(-> req :params) prints:

{:_parts [["video" {:_data {:__collector nil, :offset 0, :name "55B5E1A0-8B6F-4E5D-AB7C-75CB163BC57D.mov", :type "video/quicktime", :size 1624035, :blobId "243B8CBE-15F0-4271-9BC4-5C9A9CA15FA3"}}] ["key" "VAL"]]}
(-> req :body) prints:
#object[java.io.ByteArrayInputStream 0x284cfb69 "java.io.ByteArrayInputStream@284cfb69"]

But the file that I’m saving in my handler using

(clojure.java.io/copy (-> req :body) (clojure.java.io/file "./resources/public/video.mov")) 

is coming to be 0 bytes.
How to fix this error?

Whereas

(-> req :multipart-params)

is

{}

That parameter does not appear to be a multipart parameter, which is why it does not show up in :multipart-params.

@weavejester the parameter is requested using cljs-ajax like so:

(reg-event-fx
 :upload-shot-video-server
 (fn [coeffects [_ blob]]
   (let [body (js/FormData.)]
     (.append body "video" blob "video.mov")
     (.append body "key" "VAL")
     {:http-xhrio {:method :post
                   :uri (str "http://d18a6571c2e5.ngrok.io" "/api/upload-shot-video")
                   :body body
                   :on-success [:upload-success]
                   :on-failure [:upload-error]
                   :format (json-request-format)
                   :response-format (raw-response-format) #_(edn/edn-response-format)}}))
 )

How to make it appear as multipart parameter in the request?

Well, that's not a multipart upload, so it won't be handled by the multipart middleware. As this doesn't appear to be a problem with Ring itself, I'll close this issue. My suggestion would be to read up on XHR blob uploads, or ask in a more generic forum, like the Clojure Google group, or the Clojure slack channel.

How to perform a multipart upload then? Can you enlighten a little bit about how xhr blob upload will work with ring or how to do the upload with multipart params?
I've tried asking on Clojure slack channel to no avail.
Here are the (-> req :params) again:

{"_parts":[["video",{"_data":{"size":2971246,"blobId":"D002459C-47C5-4403-ABC6-A2DE6A46230A","offset":0,"type":"video/quicktime","name":"DCDE604A-954F-4B49-A1F9-1BCC2C2F37BC.mov","__collector":null}}],["key","VAL"]]}

there’s a filename in the request map. Where is this file stored?

If you want me to diagnose problems, please begin by showing the HTTP request being sent to the server. If you give me code that uses a third-party library, how am I supposed to infer what it is producing?

The output of (-> req :params) also looks like you're using some additional middleware. Again, I cannot infer how you're processing your request if you don't provide me with that information.