I am building a Laravel+Vue.js SPA (Single Page Application) with BootstrapVue, VeeValidate and axios as the HTTP client.
Inside axios, when I use multipart/form-data; boundary=${uploadForm._boundary}
as the Content-Type
in headers
then all the validations in Laravel Controller method fail.
But if I use 'content-type': 'multipart/form-data'
in header
then validation works except the file
input field. The file
field becomes empty in Laravel controller method.
This happens within the component EditProfile.vue
. The content there is :
<template>
<ValidationObserver ref="form" v-slot="{ passes }">
<div id="registration_form">
<div id="form_title" class="text-center">Edit Your Profile</div>
<div v-html="result" class="result text-center"></div>
<b-form name="uploadForm" @submit.prevent="passes(onSubmit)" @reset="resetForm" enctype="multipart/form-data">
<ValidationProvider vid="name" rules="required|min:2" name="name" v-slot="{ valid, errors }">
<b-form-group
label="User Name:"
label-for="exampleInput1"
>
<b-form-input
type="text"
disable-leading-trailing-space
v-model="name"
plaintext
:state="errors[0] ? false : (valid ? true : null)"
placeholder="Enter your name"
></b-form-input>
<b-form-invalid-feedback id="inputLiveFeedback">{{ errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</ValidationProvider>
<ValidationProvider vid="photo" rules="required" name="photo" v-slot="{ valid, errors }">
<b-form-group
label="Photo:"
label-for="exampleInput1"
>
<b-form-file
accept="image/x-png,image/gif,image/jpeg"
v-model="file"
:state="Boolean(file)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
@change="onFileChange" enctype="multipart/form-data"
></b-form-file>
<b-form-invalid-feedback id="inputLiveFeedback">{{ errors[0] }}</b-form-invalid-feedback>
<div class="mt-3">Selected file: {{ file ? file.name : '' }}</div>
<!-- Plain mode -->
<!--<b-form-file v-model="file2" class="mt-3" plain></b-form-file>
<div class="mt-3">Selected file: {{ file2 ? file2.name : '' }}</div>-->
<div id="preview">
<img v-if="url" :src="url" />
</div>
</b-form-group>
</ValidationProvider>
<b-button type="submit" variant="primary">Submit</b-button>
<b-button type="reset" variant="danger">Reset</b-button>
</b-form>
</div><!-- end of id registration_form-->
</ValidationObserver>
</template>
In JS part, I have :
<script>
import { ValidationObserver, ValidationProvider } from "vee-validate";
export default {
name: "EditProfile",
props: {
},
components: {
ValidationObserver,
ValidationProvider
},
data: () => ({
name: "",
photo:"",
file:"",
url:"",
result:''
}),
methods: {
onFileChange(e) {
this.file = e.target.files[0];
this.url = URL.createObjectURL(this.file);
},
onSubmit() {
console.log("Form submitted yay!");
this.result='<span class="wait">Please wait ...</span>';
axios.post('/update_profile_now',
{
name: this.name,
photo:this.file
}, // the data to post
{
headers: {
//Accept: 'application/json',
'Content-Type': `multipart/form-data; boundary=${uploadForm._boundary}`
}
})
.then(response => {
if(response.data.success){
this.result='<span class="succes">Registration completed !!</span>';
}else{
this.$refs.form.setErrors(response.data.errors);
this.result='<span class="error">Invalid data !!</span>';
}
})
.catch(error => {
if(typeof error !=="undefined"){
console.log(error);
}
});
// .finally(() => this.loading = false)
},
resetForm() {
this.name = "";
this.result='';
requestAnimationFrame(() => {
this.$refs.form.reset();
});
}
}
};
</script>
In corresponding Laravel controller method I have :
public function update_profile_now(Request $request)
{
$rules = array(
'name' => 'required | min:4',
'photo'=> 'image|mimes:jpeg,png,jpg|max:2048'
);
$validator = Validator::make(Input::all(), $rules);
// Validate the input and return correct response
if ($validator->fails())
{
return Response::json(array(
'success' => false,
'errors' => $validator->getMessageBag()->toArray()
), 200);
}
//file uploading code goes here
return Response::json(array('success' => true), 200);
}
What I want is the form with a file
input inside it will be submitted and then a JSON response will be sent from the method after file upload and other works.
So what should be the correct header or do I need to adopt any other means ?