23

First of all, i've checked questions file-upload-in-vuetify and vuetify-file-uploads. But the solutions there didn't work.

I'm trying to use vuetify 2 <v-file-input> to send multiple PDF files. I created the FormData object and appended all my files but when i attempt to submit it doesn't reach my backend. I just get an empty object. this is my code:

Template:

<v-layout>
    <v-flex>
      <v-file-input show-size counter chips multiple label="Arquivo Geral" ref="myfile" v-model="files"></v-file-input>
    </v-flex>
    <v-flex>
      <v-btn color="primary" text @click="submitFiles">test</v-btn>
    </v-flex>
</v-layout>

script:

data() {
    return {
        files: null,
    }
}
methods: {
    submitFiles(){
        let formData = new FormData()

        if(this.files){

            for( let file in this.files){
                formData.append("cave", file)
            }

            console.log(formData.getAll("cave"))
            console.log(this.files)
            axios.post('https://eniwp6w65oc77.x.pipedream.net/', 
                        {
                            files: formData,
                            test: "test"
                        }, 
                        { 
                            headers: { 
                                'Content-Type': 'multipart/form-data'
                            } 
                        }).then( response => {
                            console.log('Success!')
                            console.log({response})
                        }).catch(error => {
                            console.log({error})
                        })
        }
        else {
            console.log('there are no files.')
        }
    }
}

my response body and header in requestbin:

body:

{
    "files": {},
    "test": "test"
}

header:

host: eniwp6w65oc77.x.pipedream.net
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,pt;q=0.8,gl;q=0.7
Cache-Control: no-cache
Content-Type: multipart/form-data
Origin: http://localhost:8000
Pragma: no-cache
Referer: http://localhost:8000/
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36
Content-Length: 28
Connection: keep-alive
Marcelo Fonseca
  • 1,705
  • 2
  • 19
  • 38
  • Can you show your backend – ßiansor Å. Ålmerol Sep 03 '19 at 14:49
  • hi @MarcelusTrojahn , the main problem is my formData object, in "files" key, arrives empty in my requestbin link. whats causing this i don't know. I suspect the problem could be in the request or how i am making my formData object. The request in client-side is my axios post request in "scripts" code. I added the missing request header on server-side. – Marcelo Fonseca Sep 03 '19 at 16:43
  • @ßiansorÅ.Ålmerol i've been using requestbin to test my response. I updated with both header and body now – Marcelo Fonseca Sep 03 '19 at 16:46

1 Answers1

27

First of all, you have two bugs in code:

  1. Where you're preparing FormData object. You can't use for-in loop for iterating an array of files here since for-in loops over enumerable property names of an object. You can use for-of loop instead.

  2. You're using formData in brackets. You should pass FormData instance, not JSON. To send aditional paramaters like "test" using FormData do formData.append("test", "foo bar")

Also check that your backend properly handles multipart/form-data data. If your backend is in Node.js and Express.js then you should use proper body parser middleware, for example multer

Here is a working example:

Node.js/Express.js backend:

const multer = require("multer"),
...    
router.post("/upload-files", multer().array("files"), function (req, res) {
    console.log("body: ", req.body);
    console.log("files:", req.files);
    return res.sendStatus(200);
});

frontend:

submitFiles() {
    if (this.files) {
        let formData = new FormData();

        // files
        for (let file of this.files) {
            formData.append("files", file, file.name);
        }

        // additional data
        formData.append("test", "foo bar");

        axios
            .post("/upload-files", formData)
            .then(response => {
                console.log("Success!");
                console.log({ response });
            })
            .catch(error => {
                console.log({ error });
            });
    } else {
        console.log("there are no files.");
    }
}

Note that you don't need to set Content-Type header manually when you pass FormData as a POST request body

Yurii Semeniuk
  • 933
  • 8
  • 13
  • thanks! i changed fo...in to for...of. But it still doesnt :( i must be missing something – Marcelo Fonseca Sep 04 '19 at 17:30
  • 1
    @MarcelusTrojahn, `axios.post(url, formData)` works fine. `formData` should be an instance of FormData, not a plain JSON. I think the problem is with your backend. Could you provide your backend code? – Yurii Semeniuk Sep 04 '19 at 18:41
  • figured it out. I was using formData between brackets in my body request. In the end my code had 2 errors. The For..in and formData between brackets. Your example works fine. Thanks Yurii – Marcelo Fonseca Sep 05 '19 at 14:15
  • The formData javascript object was the key to make it work, thank you so much! – Luan Cardoso Dec 23 '21 at 13:05