'formData.append() is not sending file to the server?

I am writing some React.js that will upload multiple photos at a time. I am currently trying to send a batch of photos to the server but I cannot seem to get the files to append to the formData.

I call this function on the onChange event of the input field:

batchUpload(e) {
    e.preventDefault();

    let files = e.target.files;

    for (let i = 0; i < files.length; i++) {
        let file = files[i],
            reader = new FileReader();
        reader.onload = (e) => {
            let images = this.state.images.slice();

            if (file.type.match('image')) {
                images.push({file, previewURL: e.target.result});
                this.formData.append('files', file); //THIS IS NOT APPENDING THE FILE CORRECTLY
                this.setState({images});
            }
        };
        reader.readAsDataURL(file);
    }

    this.props.setFormWasEdited(true);
}

Then once the save button is pressed I run this function:

saveClick(goBack, peopleIdArray) {
    if (this.state.images.length > 0) {

        let formData = this.formData;
        formData.append('token',  Tokens.findOne().token);
        formData.append('action', 'insertPhotoBatch');
        formData.append('tags', peopleIdArray);
        formData.append('date', dateString());

        for (var pair of formData.entries()) {
            console.log(pair[0] + ', ' + JSON.stringify(pair[1]));
        }

        let xhr = new XMLHttpRequest();

        xhr.open('POST', Meteor.settings.public.api, true);
        xhr.onload = (e) => {
            if (xhr.status === 200) {
                // upload success
                console.log('XHR success');
            } else {
                console.log('An error occurred!');
            }
        };
        xhr.send(formData);

    } else {
        //signifies error
        return true;
    }
}

Everything seems to be fine until I append the files to the formData. What am I doing wrong?



Solution 1:[1]

If I'm not mistaken you problem is with this.formData.append('files', file); Running this line in a for loop will get you 1 field with all the file appended to each other resulting in an invalid file.

Instead you must file the file "array" syntax used informs like so:

this.formData.append('files[]', file);

This way you get the files on server side as $_FILES['files']['name'][0], $_FILES['files']['name'][1], ... and like wise for other properties of the files array.

Solution 2:[2]

I hope you have solved your issues already. I am still stuck not understanding why it would seem that my formData is not bringing anything to my server, but I did find an issue with your code.

When you use

JSON.stringify(pair[1])

the result looks like an empty array. If you instead try

pair[1].name 

you'd see that append actually did attach your file.

Solution 3:[3]

 const config = {
            headers: { 'content-type': 'multipart/form-data' }
        }
        const formData = new FormData();
    
        Object.keys(payload).forEach(item => {
            formData.append([item], payload[item])
        })

pass this formData to your API.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JDuarteDJ
Solution 2 everstrivin
Solution 3 Jean-François Fabre