1

I am trying to upload files using web fetch api and PHP. But for some reason the files are not being captured (or sent?) from the web browser to the server. I can still send files with curl though.

async function send_files(url, files) { // files = [File(), File(), ...], url = localhost
    const formData = new FormData()
    for (const file of files) {
        formData.append('files[]', file)
    }
    var result = await fetch(url, {
        method: 'POST',
        cors: 'same-origin',
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        body: formData
    })
    return await result.json()
}

And in PHP if I print_r($_FILES) it returns an empty array. Now I know that uploading is working as curl confirms this:

curl -k -X POST -c ... -b ... -H "Content-Type: multipart/form-data" -F "files[]=@file1" -F "files[]=@file2" ... https://localhost

The request payload in the networking tab in my web shows:

------WebKitFormBoundaryXXXXXXXXXXXXXXXX
Content-Disposition: form-data; name="files[]"; filename="file1"
Content-Type: text/plain


------WebKitFormBoundaryXXXXXXXXXXXXXXXX
Content-Disposition: form-data; name="files[]"; filename="file2"
Content-Type: text/plain


------WebKitFormBoundaryXXXXXXXXXXXXXXXX--

The networking tab also shows I am only sending 372 B of info to the server, and the combined size of the two files are 941 B. I am not getting any errors either on front end or back end.

4
  • How are you calling that send_files function, where does the content of the files parameter come from? Commented Jul 11, 2019 at 9:08
  • The send_files is called in other async functions with await send_json(...), then data.json() as all my responses are json formatted. The files array is filled with File() objects. This array is filled with an input type file that is captured with javascript and placed into an array. with files = [...files, ...event.target.files]. Along side that I have a drag and drop file that does files = [...files, ...event.dataTransfer.files]. Commented Jul 11, 2019 at 16:46
  • 1
    For some reason it’s behaving as if the Content-Type was application/x-www-form-urlencoded - if a form was submitted that way, only the file names of file input fields gets submitted. Commented Jul 12, 2019 at 6:19
  • I even tried it with plain html input and form submit setup with multipart/form-data and it is sending the same payload. Commented Jul 15, 2019 at 4:56

1 Answer 1

3

I managed to solve the problem, but honestly it makes no sense to me, confirmed with both firefox and brave browser (thought it might be browser related, its not).

Simply, I needed to remove the headers...

So, the call looks like:

async function send_files(url, files) { // files = [File(), File(), ...], url = localhost
    const formData = new FormData()
    for (const file of files) {
        formData.append('files[]', file)
    }
    var result = await fetch(url, {
        method: 'POST',
        cors: 'same-origin',
        //headers: {   REMOVED
        //    'Content-Type': 'multipart/form-data'
        //},
        body: formData
    })
    return await result.json()
}

I really do not understand why, but from what I saw it seems setting the header changes something in the form data that prevents the data from uploading correctly. Even though I believe that having the header not set it should default to 'application/x-www-url-encoded'.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.