Abdul Raheem Ghani
Abdul Raheem Ghani

Reputation: 336

Get files from FormData object in laravel 5.8 sent over via Axios in Vue

I have a Laravel & Vue application where I want to upload files along with other data via axios but when I send the form, I do not see the files there in laravel.

Here is my HTML form:

<form @submit.prevent="submitForm()">
                <h5 class="card-title">Add a new Discount</h5>
                <p class="text-danger mb-3 font" style="font-size: 12px" >Required fields are marked with *</p>
                <div class="row">
                    <div class="col-md-4 form-group">
                        <InputField v-model="form.amount" classes="form-control" name="amount"
                                    placeholder="Discount amount here (required)" type="number"
                                    label="Discount Amount* : "
                                    @update:field="form.amount = $event" required="required"
                        />
                        <p class="error-field" id="erramount"></p>
                    </div>

                    <div class="col-md-4 form-group">
                        <label for="student_name"><small><b>Student Name:</b></small></label>
                        <input :value="student.name" type="text" class="form-control" id="student_name" disabled>
                    </div>

                    <div class="col-md-4 form-group">
                        <label for="batchfee"><small><b>Batch Fee (Max Discount)</b></small></label>
                        <input :value="student.fee" type="text" class="form-control" id="batchfee" disabled>
                    </div>

                </div>

                <div class="row">
                    <div class="col-md-4 form-group">
                        <label for="file"><small><b>Select File*:</b></small></label>
                        <input type="file" id="file" name="file" @change="setFile" multiple>

                        <p class="error-field" id="errattachments"></p>
                    </div>
                </div>

                <hr>

                <div class="row">
                    <div class="col-md-2" v-for="bm in bmonths">
                        <label><small><b>{{ bm.month }}-{{bm.year}}</b></small></label>
                        <input class="form-control" type="checkbox" @change="addBmonth(bm.id)" />
                    </div>
                </div>

                <button type="submit" class="btn btn-primary float-right mt-5">Save</button>
            </form>  

Here is my Vue data :

data(){
    return {

        form: {
            'amount': null,
            'student_id': null,
            'batchId': null,
            'batchfee': null,
            'attachments': null,
            'selectedBmonths': [],
        },
        student: null,
        bmonths: [],

        errors: null,


    }
},  

Here is the setFile method which is called by @change event on the file uploader:

setFile(event)
    {
        this.form.attachments = new FormData();
        this.form.attachments.append('files', event.target.files);
    }  

Here is the submitForm method that is called on submit of the form:

submitForm()
    {
        this.clearErrors();

        this.form.student_id = this.student.stdId;
        this.form.batchId = this.student.batchId;
        this.form.batchfee = parseInt(this.student.fee);
        this.form.amount = parseInt(this.form.amount);

        axios.post('/university/api/discounts', this.form)
            .then(response => {
                //this.$router.push('/university/discounts/' + response.data.id);
                console.log(response.data);
            })
            .catch(errors => {
                this.errors = errors.response.data.errors;
                console.log(errors);
                for(const key in this.form)
                {
                    if(this.errors && this.errors[key] && this.errors[key].length > 0)
                    {
                        document.getElementById('err' + key).innerHTML = this.errors[key][0];
                    }
                }
            });
    },  

Here is the laravel function that just returns the request() for checking and seeing if the files were sent correctly:

public function store(Request $request)
{
    return request();
}  

When I see the result in the console.log(), I see an empty attachments array:

console.log output

Any help is appreciated in advance.

EDIT
I still have not found any solution for this, please help me overcome this issue. Thanks

Upvotes: 2

Views: 581

Answers (1)

KaKi87
KaKi87

Reputation: 945

Issue 0 : this.form.amount must be moved out of this.form.

Solution : In order to fix issue 1, we are going to assume it was moved to this.amount.

Issue 1 : FormData cannot be used inside JSON.

Solution A : use FormData instead of JSON.

this.form = new FormData();
this.form.append('student_id', this.student.stdId);
this.form.append('batchId', this.student.batchId);
this.form.append('batchfee', parseInt(this.student.fee));
this.form.append('amount', parseInt(this.amount));

Solution B : use stringified JSON inside FormData.

this.form = new FormData();
this.form.append(
    '', // <-- choose a key here
    JSON.stringify({
        student_id: this.student.stdId,
        batchId: this.student.batchId,
        batchfee: parseInt(this.student.fee),
        amount: parseInt(this.amount)
    })
);

Issue 2 : append must be called for each file with using a key ending with [].

Solution : loop over the files.

for(const file of event.target.files)
    this.form.append('files[]', file);

Additional info

  • You no longer need to initialize this.form as an object as it would always be overwritten.
  • You may initialize this.student as an object for clarity.

Upvotes: 1

Related Questions