bigskysoftware / htmx

</> htmx - high power tools for HTML
https://htmx.org
Other
35.27k stars 1.17k forks source link

2.0.0 - File uploads using htmx.ajax no longer uploads a file #2630

Open aanon4 opened 2 weeks ago

aanon4 commented 2 weeks ago

Was previously uploading a file using htmx.ajax by passing a File object as a value. Worked great in 1.X, but switching to 2.0 and now all I get uploaded is an empty object.

1cg commented 2 weeks ago

can you post the code you are using?

aanon4 commented 2 weeks ago

What's the best way to provide this to you? It's part of a fairly large project, but this is the specific file which initiates the upload:

https://github.com/kn6plv/aredn/blob/ucode-http/files/app/main/status/e/packages.ut

1cg commented 2 weeks ago

OK, so you are including an element in a form w/ a file input? If you could boil it down to the HTML and the javascript, stripping out the accidental stuff, that would be great. I'll try it locally too.

aanon4 commented 2 weeks ago

I've tried to extract the pertinent part of the code below (this is obviously not a runnable sample). There's a input file tag and a button which, when pressed, triggers the htmx.ajax to upload the file. This works fine with 1.X. With 2.X the encoding is correct and the payload arrives on the server and is decoded as I'd expect; except the packagefile.ipk just appears to be an empty object rather than the file data.

    <div style="flex:0">
        <input type="file" accept=".ipk">
    </div>
...
    <div style="flex:0">
        <button id="fetch-and-update" hx-trigger="none" hx-encoding="multipart/form-data">Fetch and Install</button>
    </div>
...
    <script>
    (function(){
...
        htmx.on("#fetch-and-update", "click", e => {
...
            const upload = htmx.find("#package-update input[type=file]").files[0];
...
            if (upload) {
                htmx.ajax("POST", "{{request.env.REQUEST_URI}}", {
                    source: e.currentTarget,
                    values: {
                        packagename: htmx.find("#package-update input[type=file]").value.replace(/^.*\\/, ""),
                        "packagefile.ipk": upload
                    },
                    swap: "none"
                }).then(_ => htmx.find("#package-upload progress").setAttribute("value", "0"));
            }
aanon4 commented 2 weeks ago

Taking a quick look at the ajax differences between 1.X and 2.0, I see that you're using a method called formDataFromObject to process the values passed in, and this doesnt understand what a file object is (so just JSONs it). In the 1.0 code the method used was mergeObject which had a much more simplistic approach to its arguments.

LucaPanofsky commented 2 weeks ago

I think that this is also related to this issue: https://github.com/bigskysoftware/htmx/issues/2616 for now the API works with formData instead of plain objects