ring-clojure / ring

Clojure HTTP server abstraction
MIT License
3.77k stars 520 forks source link

Error with multi-part binary #368

Closed lyriccoder closed 5 years ago

lyriccoder commented 5 years ago

When I am sending result with Python to clojure server, the clojure server doesn't have tempfile parameter and corrupted file is uploaded.

I use the following code:

(defn prepare-io-wrap-multipart-params [handler]
  (-> handler
      wrap-exception-handling
      wrap-keyword-params
      wrap-params
      wrap-json-response
      wrap-multipart-params
      ))

(defn create-routes []
  (let [- (log/debug "Smth")]
    (c/routes
      (c/POST "/put_multi" [] (prepare-io-wrap-multipart-params upload/multi-part-upload rmq-context))
      (route/resources "/")
      ))
  )

(defn multi-part-upload [rmq-context req]
  (let [params (get req :params)
        filename (get params :to)
        file-binary (get params :file)
        temp-file (get-in params [:file :tempfile])
        _ (log/debug "params" params)
        resp (try
               (let [in (if (not (nil? temp-file))
                          (input-stream (get-in params [:file :tempfile]))
                          file-binary
                          )

                     _ (with-open
                         [out (output-stream "C:\users\lyriccoder\1.stl")]
                         (copy in out))

                     ]
                 {:status 200
                  :body   ""})
               (catch Exception ex
                 {:status 500
                  :body   "error"}))
        ]
    resp
    ))

I send a binary file using python:

filename = 'C:\users\lyriccoder\1.stl'
s = open(filename, 'rb')
data = {
    'to': 'DATASETS/MULTI_PART/1.stl',
    'comment': 'some comment',
    'user-name': 'lyriccoder'
}
up = {'file': (filename, s)}
r = requests.post('http://localhost:8080/put_multi', data=data, files=up)
print(r.content)
print(r)

When I receive the request, I get the following params: params {:to DATASETS/MULTI_PART/1.stl, :comment some comment, :user-name lyriccoder, :file from Cadent Ltd. h v???9?7??8??,...

So, I do not have tempfile parameter in the response, I have the content of the binary file. And when I try to save it (using input-stream/output-stream), the server saves a corrupted file.

I created a server with the following parameters: {:port 8080 :thread 42 :max-body 100388608} Could you please help me why it happens?

weavejester commented 5 years ago

I can't reproduce. Can you provide a sample project that shows the error?

Also, you want to wrap your whole routing handler in your middleware, rather than applying your middleware from scratch each request.

lyriccoder commented 5 years ago

Let me create a sample project, I need to delete all unnecessary code. I will return later