medusa-ui/medusa

File uploads

Closed this issue · 7 comments

How can we do file uploads? And, because we have bidirectional and reactive capabilities, can we have actual loading bars that reflect progress?

initial commit in rewrite-1.0.0-file-upload
still WIP

https://www.vinsguru.com/rsocket-file-upload-example/
https://stackoverflow.com/questions/64987563/stream-uploading-large-files-via-spring-webclient

I think key is that we have chunked uploads, if we can do that, we can use the serverToClient capabilities to send progress updates back.

I made a rough first iteration here: https://github.com/medusa-ui/medusa/tree/feature/upload-chunked

Basically exists out of two major changes:

  1. JS side: Use FileReader to grab local I/O file, then chunk it (literally grab the bytes and split them into pieces), then send messages over the RSocket with start, end and each chunk.
  2. Server side: Retrieving the chunks and pushing them to the controller (see FileUploadHandler)

Current limitations:

  • Only controller method (#byteArray) works, no ServerRequest and such. We can look at ActionHandler to do a similar impl in FileUploadHandler
  • idk if byte[] is the right approach? Let's say you upload a 50GB file. That would mean you would load in 50GB in memory serverside. That doesn't seem right. Each chunk is only like 50kb, so it would be fine if we'd only keep the chunk in memory. Where do you stream to, though? More importantly, how do you then use it in the controller class? Does it make more sense to stream to a local file and use a file reference? Any other options?

Demo should allow for re-uploads (should clear, redo)
Validation should tie into uploads properly

@kevindeyne Allowed re-uploading (an other picture) in demo.

Tied it into validations
Works well locally but with the speed loss of being deployed on a remote server, it still feels a bit off; so I might want to add loading to the demo before I call it 'done'

Added, was actually not working by default due to bypassing the regular onAction method in JS. Should work now.