clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2021-01-20T06:25:09.270300Z

Interesting, hadn't read that one before

2021-01-20T06:26:27.270500Z

I think he makes a great point actually. But I think it would have been nice for him to describe when does BIG become Bloated.

😄 1
borkdude 2021-01-20T14:46:45.274600Z

Does this work by design or by accident?

(clojure.core/IllegalArgumentException.)
I came across it over here: https://github.com/clojure/clojurescript/blob/0c353f1947089cb8b1f010b4294b94ac109d4ef6/src/main/clojure/cljs/core.cljc#L2293 (while implementing a new linter for clj-kondo...)

borkdude 2021-01-20T14:47:46.275400Z

(`clojure.core/IllegalArgumentException` does not resolve to the class, but the constructor does, it seems)

bronsa 2021-01-20T14:48:13.275700Z

it's a bug in macroexpand

bronsa 2021-01-20T14:48:36.276Z

user=> (macroexpand '(clojure.core/Foo.))
(new Foo)

bronsa 2021-01-20T14:51:28.276600Z

well I guess it's GIGO

bronsa 2021-01-20T14:51:50.276800Z

the namespace segment is just ignored (but because of impl details, it must also exist 🙃 )

borkdude 2021-01-20T14:52:47.277200Z

same as with protocol method impls basically

bronsa 2021-01-20T14:52:54.277500Z

ish, yeah

alexmiller 2021-01-20T14:59:00.278800Z

I know there are some weird corners in the symbol resolution, was just in that code recently, jira welcome

bronsa 2021-01-20T15:01:24.279100Z

fixing this would be a breaking change now though

bronsa 2021-01-20T15:06:42.279300Z

https://clojure.atlassian.net/browse/CLJ-2604

bronsa 2021-01-20T15:06:50.279600Z

a patch for this is trivial, lmk if you want one

bronsa 2021-01-20T15:07:32.280Z

welp :)

borkdude 2021-01-20T15:07:48.280300Z

oh eh hmm :) I'll close it

borkdude 2021-01-20T15:08:27.280500Z

done

bronsa 2021-01-20T15:09:02.280700Z

:gotta_go_fast:

mischov 2021-01-20T15:42:09.286100Z

Has anybody ever encountered issues using aliased keywords in .cljc files when both the alias and the alias keyword are inside of reader conditionals for one platform (say :clj) but you're compiling for another platform (say :cljs)? For example

(ns main
  (:require #?(:clj [<http://clojure.java.io|clojure.java.io> :as io])))

#?(:clj (defn io-world [] ::io/world)))
results in an invalid keyword error when compiling cljs.

emccue 2021-01-20T15:44:08.287400Z

wow, that is strange

mischov 2021-01-20T15:44:28.287800Z

I would have expected because the namespaced keyword is restricted to clojure it wouldn't modify cljs compilation.

bronsa 2021-01-20T15:44:50.288100Z

autoresolution of keyword happens at read time

bronsa 2021-01-20T15:45:32.288800Z

reader conditionals require all the branches to be readable

👍 1
mischov 2021-01-20T15:46:56.289400Z

Well that's unfortunate. 😕

p-himik 2021-01-20T15:52:14.290300Z

Same with comment. At least, in this case you can just use a fully qualified keyword.

mischov 2021-01-20T15:53:11.290700Z

Oh wow, commented code has to be readable in all branches?

2021-01-21T21:44:18.020500Z

No

2021-01-21T21:44:33.020700Z

Only code wrapped in the comment macro need to be.

2021-01-21T21:44:49.020900Z

If you use ; it does not need to be

dpsutton 2021-01-20T15:57:11.291200Z

comment is just a macro. there's no mechanism by which it couldn't be readable

mischov 2021-01-20T15:59:07.292700Z

I'm just surprised things have to be readable for platforms they don't apply to. I guess I had expected the reader would just skip over sections for other platforms.

dpsutton 2021-01-20T16:02:36.294300Z

yeah its a bit weird but to skip something it has to be read and discarded. to be structurally one form it has to be read. I think the autoresolve of keywords should be inhibited of branches not taken but that's not the case. I think there are some tickets about this kind of problem

👍 1
2021-01-21T21:45:43.021100Z

I think if you use the discard macro: #_ that's not the case though

2021-01-21T21:45:57.021300Z

But the following form needs to be well delimited

dpsutton 2021-01-21T21:53:08.021500Z

Clojure 1.10.1
user=&gt; #_(::invalid/discard)
Syntax error reading source at (REPL:1:21).

2021-01-21T23:19:55.026800Z

I didn't even know that was invalid syntax

2021-01-21T23:20:06.027Z

Ok, seems I was wrong then

dpsutton 2021-01-21T23:21:07.027400Z

yeah. the reader expands the aliases. if there is no alias, it barfs

dpsutton 2021-01-20T16:06:32.294600Z

https://clojure.atlassian.net/browse/CLJ-2099

zendevil 2021-01-20T16:10:06.295Z

I’m making a formdata post request like so:

zendevil 2021-01-20T16:11:16.296Z

using http-xhrio in a re-frame handler

{:http-xhrio (http-post "/api/upload-shot-video" {:video body}
   [:upload-success]
   [:upload-error])}
     

zendevil 2021-01-20T16:11:24.296300Z

where http-post is the following:

zendevil 2021-01-20T16:11:48.296500Z

(defn http-post [uri params on-success on-failure]
  {:method :post
   :uri (str "<http://d18a6571c2e5.ngrok.io>" uri)
   :params params
   :on-success on-success
   :on-failure on-failure
   :response-format (edn/edn-response-format)
   :format (edn/edn-request-format)
   })

zendevil 2021-01-20T16:12:19.297Z

However, I’m getting the following error on the server:

zendevil 2021-01-20T16:12:43.297400Z

clojure.lang.ExceptionInfo: Malformed application/edn request. {:type :muuntaja/decode, :default-format "application/json", :format "application/edn", :charset "utf-8", :request {:reitit.core/match #reitit.core.Match{:template "/api/upload-shot-video", :data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :result #reitit.ring.Methods{:get #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :get, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :head #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :head, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :post #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :post, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :put #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :put, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :delete #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :delete, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :connect #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :connect, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :options #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :options, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :trace #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :trace, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}, :patch #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats] #function[ring.middleware.multipart-params/wrap-multipart-params]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :patch, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil} #reitit.middleware.Middleware{:name nil, :wrap #function[ring.middleware.multipart-params/wrap-multipart-params], :spec nil}]}}, :path-params {}, :path "/api/upload-shot-video"}, :reitit.core/router #object[reitit.core$lookup_router$reify__11769 0x6741233b "reitit.core$lookup_router$reify__11769@6741233b"], :aleph/request-arrived 150075890045367, :aleph/keep-alive? true, :cookies {}, :remote-addr "0:0:0:0:0:0:0:1", :params {}, :flash nil, :headers {"host" "<http://d18a6571c2e5.ngrok.io|d18a6571c2e5.ngrok.io>", "user-agent" "Humboi/1 CFNetwork/1206 Darwin/20.1.0", "content-type" "application/edn", "content-length" "42", "accept" "application/edn", "accept-language" "en-us", "x-forwarded-for" "110.225.238.196", "accept-encoding" "gzip, deflate"}, :server-port 3000, :form-params {}, :session/key nil, :query-params {}, :uri "/api/upload-shot-video", :server-name "localhost", :query-string nil, :path-params {}, :body #object[java.io.ByteArrayInputStream 0x7f2c96a7 "java.io.ByteArrayInputStream@7f2c96a7"], :multipart-params {}, :scheme :http, :request-method :post, :session {}}}
	at muuntaja.core$fail_on_request_decode_exception.invokeStatic(core.clj:132)
	at muuntaja.core$fail_on_request_decode_exception.invoke(core.clj:126)
	at muuntaja.core$create$_decode_request_body__8194.invoke(core.clj:424)
	at muuntaja.core$create$reify__8216.negotiate_and_format_request(core.clj:491)
	at muuntaja.middleware$wrap_format$fn__8285.invoke(middleware.clj:72)
	at humboiserver.middleware$wrap_formats$fn__9418.invoke(middleware.clj:38)
	at reitit.ring$ring_handler$fn__12248.invoke(ring.cljc:326)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.lang.AFunction$1.doInvoke(AFunction.java:31)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:384)
	at ring.middleware.reload$wrap_reload$fn__4463.invoke(reload.clj:39)
	at selmer.middleware$wrap_error_page$fn__4478.invoke(middleware.clj:18)
	at prone.middleware$wrap_exceptions$fn__4719.invoke(middleware.clj:159)
	at ring.middleware.flash$wrap_flash$fn__8523.invoke(flash.clj:39)
	at ring.middleware.session$wrap_session$fn__8890.invoke(session.clj:108)
	at ring.middleware.keyword_params$wrap_keyword_params$fn__8936.invoke(keyword_params.clj:53)
	at ring.middleware.nested_params$wrap_nested_params$fn__8994.invoke(nested_params.clj:89)
	at ring.middleware.multipart_params$wrap_multipart_params$fn__9126.invoke(multipart_params.clj:171)
	at ring.middleware.params$wrap_params$fn__9150.invoke(params.clj:67)
	at ring.middleware.cookies$wrap_cookies$fn__8841.invoke(cookies.clj:214)
	at ring.middleware.absolute_redirects$wrap_absolute_redirects$fn__9338.invoke(absolute_redirects.clj:47)
	at ring.middleware.resource$wrap_resource_prefer_resources$fn__9186.invoke(resource.clj:25)
	at ring.middleware.content_type$wrap_content_type$fn__9286.invoke(content_type.clj:34)
	at ring.middleware.default_charset$wrap_default_charset$fn__9310.invoke(default_charset.clj:31)
	at ring.middleware.not_modified$wrap_not_modified$fn__9252.invoke(not_modified.clj:61)
	at ring.middleware.x_headers$wrap_x_header$fn__8486.invoke(x_headers.clj:22)
	at ring.middleware.x_headers$wrap_x_header$fn__8486.invoke(x_headers.clj:22)
	at ring.middleware.x_headers$wrap_x_header$fn__8486.invoke(x_headers.clj:22)
	at humboiserver.middleware$wrap_internal_error$fn__9412.invoke(middleware.clj:17)
	at aleph.http.server$handle_request$fn__19409$f__14156__auto____19410.invoke(server.clj:158)
	at clojure.lang.AFn.run(AFn.java:22)
	at io.aleph.dirigiste.Executor$Worker$1.run(Executor.java:62)
	at manifold.executor$thread_factory$reify__14038$f__14039.invoke(executor.clj:44)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.lang.Thread.run(Thread.java:748)
Caused by: clojure.lang.ExceptionInfo: Malformed application/edn in :muuntaja/decode {:type :muuntaja/decode, :format "application/edn"}
	at muuntaja.core$on_exception.invokeStatic(core.clj:284)
	at muuntaja.core$on_exception.invoke(core.clj:267)
	at clojure.core$partial$fn__5839.invoke(core.clj:2626)
	at muuntaja.core$create_coder$decode__8144.invoke(core.clj:322)
	at muuntaja.core$create$_decode_request_body__8194.invoke(core.clj:422)
	... 34 more
Caused by: java.lang.RuntimeException: No reader function for tag object
	at clojure.lang.EdnReader$TaggedReader.readTagged(EdnReader.java:801)
	at clojure.lang.EdnReader$TaggedReader.invoke(EdnReader.java:783)
	at clojure.lang.EdnReader$DispatchReader.invoke(EdnReader.java:549)
	at clojure.lang.EdnReader.readDelimitedList(EdnReader.java:757)
	at clojure.lang.EdnReader$MapReader.invoke(EdnReader.java:680)
	at clojure.lang.EdnReader.read(EdnReader.java:145)
	at clojure.lang.EdnReader.read(EdnReader.java:111)
	at clojure.edn$read.invokeStatic(edn.clj:35)
	at clojure.edn$read.invoke(edn.clj:14)
	at muuntaja.format.edn$decoder$reify__7763.decode(edn.clj:12)
	at muuntaja.core$create_coder$decode__8144.invoke(core.clj:320)
	... 35 more

zendevil 2021-01-20T16:12:43.297500Z

How to fix this error?

dpsutton 2021-01-20T16:13:43.298Z

Malformed application/edn No reader function for tag object. You're serializing something that shouldn't be serialized

jtkdvlp 2021-01-20T16:19:34.298600Z

probably your video body is of the wrong type

zendevil 2021-01-20T16:22:29.299100Z

I’m trying to upload a video to the server from its url in ios

zendevil 2021-01-20T16:24:40.299600Z

Here’s more code:

zendevil 2021-01-20T16:24:44.299800Z

(let [video {:uri (-&gt; coeffects :db :shot-video-uri)}
         body (js/FormData.)]
     (.append body "video" video)
     {:http-xhrio (http-post "/api/upload-shot-video" {:video body}
  [:upload-success]
  [:upload-error]}
    ))

zendevil 2021-01-20T16:27:58.300800Z

@jtkdvlp body is of type FormData

p-himik 2021-01-20T16:31:01.302300Z

IIRC FormData has to be the body itself - you cannot wrap it into an extra object like {:video ...}.

p-himik 2021-01-20T16:32:51.303Z

Seems like in your case above you can just replace {:video body} with body.

zendevil 2021-01-20T16:36:08.303600Z

@p-himik unfortunately I’m still getting the error after replacing {:video body} with body

dgb23 2021-01-20T16:36:41.304800Z

You might want to check the mdn resources on FormData.

p-himik 2021-01-20T16:36:46.305100Z

Ah, you also have :format (edn/edn-request-format) - don't do that.

jtkdvlp 2021-01-20T16:37:01.305300Z

yeah maybe you try to send form-data binary array as edn?

p-himik 2021-01-20T16:37:46.305700Z

@ps Try just removing the line with :format from http-post..

dgb23 2021-01-20T16:39:38.307200Z

Here is a little JS snippet that might interest you:

const form_entries = (new FormData($form)).entries();
const params = [...form_entries];

// params is a JS-array now

dgb23 2021-01-20T16:40:30.307700Z

Oops we’re in #clojure here. I thought this is related to #clojurescript

p-himik 2021-01-20T16:41:49.308Z

It doesn't have to be an array. You can just send a single FormData object.

p-himik 2021-01-20T16:42:03.308500Z

The issue is that OP is trying to serialize it as EDN.

zendevil 2021-01-20T16:42:12.308800Z

@p-himik removing format gives unrecognized request format nil

dgb23 2021-01-20T16:42:21.308900Z

Yeah, that’s why you’d want to convert it first right?

dgb23 2021-01-20T16:42:34.309100Z

So this is actually a clojurescript question?

p-himik 2021-01-20T16:44:20.309300Z

That shouldn't happen because the error is thrown only when :body is nil. Can you post here the full code that you have right now?

p-himik 2021-01-20T16:45:18.309500Z

You don't want to convert it at all - you just have to send raw FormData because the underlying platform (JavaScript) knows how to handle it. Yes, it ends up being a CLJS question. Or even a cljs-ajax question.

👍 1
zendevil 2021-01-20T16:45:37.309700Z

(reg-event-fx
 :upload-shot-video
 (fn [coeffects _]
   (prn "uploading video")
   (let [video {:uri (-&gt; coeffects :db :shot-video-uri)}
         body (js/FormData.)]
     (.append body "video" video)
     {:http-xhrio {:method :post
                   :uri (str "<http://d18a6571c2e5.ngrok.io>" "/api/upload-shot-video")
                   :params body
                   :on-success [:upload-success]
                   :on-failure [:upload-error]
                   :response-format (edn/edn-response-format)
                   ;;:format (edn/edn-request-format)
                   }}
     #_(POST "/api/upload-shot-video"
             {:body body
              :response-format :json
              :keywords? true
            :handler #(dispatch [:upload-success %])
            :error-handler #(dispatch [:upload-error %])})
     )))

p-himik 2021-01-20T16:46:06.309900Z

Ah, I missed one thing. Replace :params body with :body body.

zendevil 2021-01-20T16:50:08.310100Z

@p-himik thanks the error has disappeared

👍 1
zendevil 2021-01-20T16:52:39.310400Z

but the params are empty in the server

zendevil 2021-01-20T16:53:46.310600Z

Here’s the handler:

(defn upload-shot-video [req]
(prn "video is! " (-&gt; req :params))
  (r/response {:res "okay!"}))

zendevil 2021-01-20T16:54:22.310900Z

and I’m getting:

"video is! " {:video ""}

p-himik 2021-01-20T16:55:36.311100Z

I don't know what you're using on your server so I can't really help. My assumption is that you have the content not in (:params req) but some place else. Maybe (:body req) - at least, that would be logical.

p-himik 2021-01-20T16:55:56.311300Z

I will probably be a binary stream.

zendevil 2021-01-20T16:57:54.311500Z

that’s right. there’s a stream at (-> req :body)

p-himik 2021-01-20T16:58:12.311700Z

Well there you have it. :) Seems like all is fine.

zendevil 2021-01-20T16:58:55.311900Z

thanks a ton!

p-himik 2021-01-20T16:59:24.312100Z

NP

zendevil 2021-01-20T17:04:53.312300Z

@p-himik while we’re at it, do you know how to convert an input stream to a file?

zendevil 2021-01-20T17:05:04.312500Z

that can be saved to disk?

p-himik 2021-01-20T17:07:09.312700Z

Look at the functions in the <http://clojure.java.io|clojure.java.io> namespace. I don't exactly remember the way to do it.

dgb23 2021-01-20T17:15:41.313Z

Ah right, I assumed that the library used here strictly expects serializable data. Your other answer (changing to :body) explained it for me thanks

👍 1
zendevil 2021-01-20T17:45:37.313900Z

How to convert an inputstream to an outputstream?

zendevil 2021-01-20T17:46:03.314100Z

I try the following:

zendevil 2021-01-20T17:46:03.314300Z

(http://clojure.java.io/make-output-stream (-> req :body))

zendevil 2021-01-20T17:46:17.314500Z

but get the following error:

zendevil 2021-01-20T17:46:19.314700Z

No single method: make_output_stream of interface: http://clojure.java.io.IOFactory found for function: make-output-stream of protocol: IOFactory

2021-01-20T17:49:55.315200Z

@ps I think the most straightforward thing is io/copy to copy the input stream to the ouput

2021-01-20T17:50:34.316100Z

there is no such thing as "converting an inputstream to an outputstream"

2021-01-20T17:50:36.316200Z

@ps actually, thinking more about this - what is the output-stream for?

2021-01-20T17:50:46.316700Z

an output-stream is something you can write to

zendevil 2021-01-20T17:50:48.316900Z

@noisesmith to convert to a file on disk

2021-01-20T17:50:59.317400Z

how is copying an input stream to it meaningful?

2021-01-20T17:51:00.317600Z

OK

2021-01-20T17:51:04.317800Z

that's different, and yeah, use io/file and io/copy

zendevil 2021-01-20T17:51:26.318500Z

I have a video as an input stream on the server that I’m trying to load on aws as a file

2021-01-20T17:51:47.319200Z

that's not creating an output-stream to be clear

zendevil 2021-01-20T17:52:08.319700Z

for that I’m saving it as a file. I thought to save as a file, it first needs to be converted to an outputstream

2021-01-20T17:52:26.320Z

the file provides an output-stream

2021-01-20T17:52:28.320200Z

you write to that

zendevil 2021-01-20T17:55:14.321Z

@noisesmith I have the following now:

zendevil 2021-01-20T17:55:25.321400Z

(with-open [o (<http://clojure.java.io/output-stream|clojure.java.io/output-stream> "./resources/public/video.mp4")]
  (.write o (-&gt; req :body))
    )

zendevil 2021-01-20T17:55:28.321600Z

but this gives:

2021-01-20T17:55:38.321900Z

$ scrot -s foo.png
$ clj
Clojure 1.10.1
user=&gt; (require '[<http://clojure.java.io|clojure.java.io> :as io])
nil
user=&gt; (io/copy (io/file "foo.png") (io/file "bar.png"))
nil
user=&gt; 
$ cmp foo.png bar.png
$ echo $?
0

zendevil 2021-01-20T17:55:40.322200Z

java.lang.IllegalArgumentException: No matching method write found taking 1 args for class http://java.io.BufferedOutputStream

2021-01-20T17:55:44.322300Z

all you need is io/file and io/copy

2021-01-20T17:55:51.322500Z

don't use the .write method

2021-01-20T17:56:33.323200Z

(if you don't understand shell, the above example copies a png file, and cmp verifies that byte for byte the copy is the same as the original)

zendevil 2021-01-20T17:56:54.323500Z

in the example you are copying a file

zendevil 2021-01-20T17:57:00.323800Z

I have an input stream

2021-01-20T17:57:07.324Z

right, the first arg can be an input stream

2021-01-20T17:57:13.324300Z

io/copy is smart enough to do the right thing

2021-01-20T17:58:37.325100Z

so (io/copy (:body req) (io/file "resources/public/video.mp4"))

dpsutton 2021-01-20T17:59:04.325800Z

(doc <http://clojure.java.io/copy|clojure.java.io/copy>)
-------------------------
<http://clojure.java.io/copy|clojure.java.io/copy>
([input output &amp; opts])
  Copies input to output.  Returns nil or throws IOException.
  Input may be an InputStream, Reader, File, byte[], char[], or String.
  Output may be an OutputStream, Writer, or File.

  Options are key/value pairs and may be one of

    :buffer-size  buffer size to use, default is 1024.
    :encoding     encoding to use if converting between
                  byte and char streams.   

  Does not close any streams except those it opens itself 
  (on a File).

🙏 1
2021-01-20T17:59:07.326Z

also, be cautious about writing to resources/public, usually resources is where you want to put things that would go in a jar, and you can't write a file to it like that

zendevil 2021-01-20T18:00:14.326200Z

thanks @noisesmith!

zendevil 2021-01-20T18:01:38.326800Z

unfortunately the video is 0 bytes

zendevil 2021-01-20T18:02:14.327400Z

it’s supposed to be more than 0 bytes

2021-01-20T18:03:20.328500Z

a problem I've frequently seen is some ring middleware consuming the request body before my code sees it

zendevil 2021-01-20T18:04:17.329100Z

@noisesmith as far as I know, I’m using two: middleware/wrap-formats wrap-multipart-params

2021-01-20T18:10:16.330300Z

@ps wrap-multiplart-params already wants to put your upload in a file https://github.com/ring-clojure/ring/wiki/File-Uploads

2021-01-20T18:11:30.331700Z

(I have found this annoying in the past, eg. when I'm running on a cloud server, all I'd ever do with that file is write it back to the network for storage elsewhere, but everyone seems to accept that and just read the file back to upload... pointless use of disk)

2021-01-20T18:12:17.332200Z

> By default, uploads are stored in temporary files that are deleted an hour after being uploaded. This is handled by https://github.com/ring-clojure/ring/blob/1.6.3/ring-core/src/ring/middleware/multipart_params/temp_file.clj function.

🙏 1