I have a method for Vuejs component:
async submit () {
if (this.$refs.form.validate()) {
let formData = new FormData()
formData.append('userImage', this.avatarFile, this.avatarFile.name)
this.avatarFile = formData
try {
let response = await this.$axios.post('http://localhost:3003/api/test.php', {
avatar: this.avatarFile,
name: this.name,
gender: this.gender,
dob: this.DOB,
}, {
headers: {
'Content-Type': 'multipart/form-data; boundary=' + formData._boundary
}
})
if (response.status === 200 && response.data.status === 'success') {
console.log(this.response)
}
} catch (e) {
console.log(e)
}
}
}
And in test.php
, I'm using json_decode(file_get_contents("php://input"), TRUE);
to read data as $_POST
variables.
While I am able to read name
, gender
and dob
correctly, I can't fetch avatar
properly.
Any solutions for the same?
Note: I don't to append every variable as formData.append(.., ..)
as I am planning to handle over 14 variables.
Note for moderators: I didn't find any question where formData was being used along with other data objects.
To send multipart form data with Axios, you need to use the FormData class. Browsers have a built-in FormData class, but Node. js doesn't, so you need to use the form-data npm module. To create the form, you must append the data to the form that will be sent to the server using the append() method.
new Vue({ el: 'body', methods: { submit: function(e) { var form = document. getElementById('form'); var formData = new FormData(form); axios. post('/someUrl', formData) . then((response) => { // success callback }, (response) => { // error callback }); } } });
Multipart/form-data is one of the most used enctype/content type. In multipart, each of the field to be sent has its content type, file name and data separated by boundary from other field. No encoding of the data is necessary, because of the unique boundary. The binary data is sent as it is.
So, I figured this one out in a simpler way:
let rawData = {
name: this.name,
gender: this.gender,
dob: this.dob
}
rawData = JSON.stringify(rawData)
let formData = new FormData()
formData.append('avatar', this.avatarFile, this.avatarFile.name)
formData.append('data', rawData)
try {
let response = await this.$axios.post('http://localhost:3003/api/test.php', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
test.php:
$_POST = json_decode($_POST['data'],true);
Note: I had an option of using:
Object.keys(rawData).map(e => {
formData.append(e, rawData[e])
})
but since I was dealing with nested objects (name: { first: '', last: ''} )
in rawData, I chose not to do that as it would require recursive methods on either client side or server side.
PHP ( process.php )
<?php
$data = array(
"post" => $_POST,
"files" => $_FILES
);
echo json_encode($data);
?>
Vue and form HTML
let vm = new Vue({
el: "#myApp",
data: {
form: {}
},
methods: {
submit: async function (e) {
e.preventDefault();
/* formData */
var formData = new FormData( this.$refs.formHTML );
/* AJAX request */
await axios({
method: "post",
url: "process.php",
data: formData,
config: { headers: { "Content-Type": "multipart/form-data" } }
})
/* handle success */
.then( response => { console.log(response.data); } )
/* handle error */
.catch( response => { console.log(response) } );
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<div id="myApp" >
<form @submit="submit" ref="formHTML" >
Name: <input type="text" name="name" v-model="form.name" /><br />
Gender:
<input type="radio" name="gender" value="male" v-model="form.gender" /> Male
<input type="radio" name="gender" value="female" v-model="form.gender" /> Female <br />
File: <input type="file" name="upload" v-model="form.upload" /><hr />
<input type="submit" name="submit" value="Submit" />
</form>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With