bigskysoftware / htmx-extensions

103 stars 30 forks source link

Enhancement request: WebSocket extension should handle file uploads #17

Open aral opened 3 months ago

aral commented 3 months ago

The WebSocket extension currently does not handle file uploads.

To reproduce

Submit a form via WebSocket that has a file input:

<form
  hx-ext="ws"
  ws-connect="wss://path/to/your/socket/handler"
  name="fileUploadForm"
  ws-send
>
  <input
    name="fileToUpload"
    type="file"
    required
  >
  <button>Upload</button>
</form>

What should happen

You should get the serialised contents of the file in a field called fileToUpload.

What actually happens

As file upload functionality is not currently implemented, you get an empty object instead, along with the standard headers:

{
  fileToUpload: {},
  HEADERS: {
    …
  }
}

Implementation suggestion

The file’s contents could be read in using the File Reader API and serialised to the JSON object.

Note that including the files contents in the JSON will not be the most performant option, especially for larger files, but I’m not sure what else can be done here while still keeping things easy to use. (Open to ideas) :)

Workaround

You should be able to implement this manually in your htmx:wsConfigSend handler.

aral commented 3 months ago

A little update:

Having thought about this more, I’m not sure whether the WebSocket extension should be handling file uploads or not.

The part of me that wants a nice unified interface says it should.

The part of me that doesn’t want to reinvent the wheel with a suboptimal solution says it shouldn’t.

POST routes already handle file uploads beautifully. So, for the time being, in Kitten, at least, I’ve decided to implement a hybrid approach where the WebSocket-based workflow (which I call the Streaming HTML workflow in Kitten) is used for status updates whereas a regular POST route is used to handle the actual upload. This is working well for me so far.

You can see an example/brief write up of the process here:

https://codeberg.org/kitten/app/src/branch/backup-and-restore/examples/streaming-html/file-uploads

This is not to say that there might not be a third way that both simplifies usage and doesn’t add lots of overhead but I can’t think of one at the moment.