Triggers, forms, and feedback

Upload a file

Use multipart form encoding and a real file input so the server receives binary data with the other form values.

8 minute lesson

~~~

A real upload form needs multipart encoding:

<form action="/attachments" method="post"
  enctype="multipart/form-data"
  hx-post="/attachments"
  hx-target="#upload-result">
  <label>
    Attachment
    <input type="file" name="attachment" accept="image/*" required>
  </label>
  <button>Upload</button>
</form>

<div id="upload-result"></div>

You can alternatively set hx-encoding="multipart/form-data" on the HTMX request context. Keep the native enctype when the form must work without JavaScript.

HTMX uses XMLHttpRequest, so htmx:xhr:progress can drive a progress display for large uploads. Treat it as feedback, not proof that the server accepted or stored the file.

The server must enforce a size limit, inspect actual content rather than trusting the filename or MIME declaration, generate a safe storage name, authorize who may attach the file, and keep uploads outside executable paths. accept="image/*" only filters the chooser.

Test an oversized file, a renamed non-image, a lost connection, and a valid upload. Every path needs a recoverable response.

Lesson completed