I'm trying to send an input of file along with an input of text in a single request using Axios and FormData in Vue.js. I've read that it is very simple, just do :
const formData = new FormData();
formData.append('file', file);
formData.append('text', text);
axios.post('ajax.php', formData)
.then(function (response){
console.log(response.data);
})
But that only works for some absurd reason if “text” is an integer. This is the HTML code that I'm using for the form :
<div v-for="(gallery, i) in galleryMeta">
<form @submit.prevent="editData('gallery', gallery.Id, i)">
<div >
<div >
<div >
<h6 >Title:</h6>
<div >
<input type="text" v-model="gallery.Title">
<input type="text" v-model="gallery.Title">
</div>
</div>
</div>
<div >
<div >
<label for="file">EDIT</label>
<input type="file" id="file" ref="file" style="display: none;" accept="image/jpeg,image/png,image/webp" @change="pickData">
<button @click="editData('gallery', gallery.Id, i)">UPLOAD</button>
</div>
</div>
</div>
</form>
</div>
The form works just fine for everything else. This is the Vue.js code :
let app = Vue.createApp({
data: function(){
return{
File: '',
}
},
methods:{
pickData: function (){
this.File = event.target.files[0];
},
editData: function (requestSection, Id, i, Title){
if(requestSection === 'gallery'){
const formData = new FormData();
formData.append('file', this.File);
formData.append('id', Id);
formData.append('title', this.galleryMeta[i].Title);
axios.post('ajax.php', formData, {
header: {
'Content-Type': 'multipart/form-data'
}
}
.then(function (response){
console.log(response.data);
}
}
}
})
This is the ajax.php file to handle the Axios AJAX request :
<?php
$data = json_decode(file_get_contents("php://input"));
$request = $data->request;
if(isset($_FILES['file']['name'])){
$id = json_decode($_POST['id']);
$title = json_decode($_POST['title']);
$file = file_get_contents($_FILES['file']['tmp_name']);
}
?>
You may've noticed the 2 first lines in the PHP code. The reason for why they're there is that in the same PHP file I'm also handling other simple Axios POSTS requests by data binding, which all work properly. Although I believe that they do not cause any issues related to this, I'm including them just in case they do.
In the PHP file $id
is defined properly, $file
is defined properly however $title
never is no matter what I do. After hours of intense troubleshooting, I've found that strings never make it past the Axios request, ever. If I change :
formData.append('title', this.galleryMeta[i].Title);
to
formData.append('title', '20');
It is immediately sent properly. The problem is not in the galleryMeta
array of objects if I set the Title
in galleryMeta
to a random number everything works. All the variables that I'm using in the JavaScript code are properly defined. I tried to console.log() every single bit of that code, and all the variables contain their respective proper expected values, always. But strings never get parsed by Axios AJAX at all. It doesn't matter how long the string is or what does it contain, it just won't get past the request. I've also checked the values of that formData
form with this loop :
for (var value of formData.values()) {
console.log(value);
}
And they're all there, assigned properly, just like I wanted. So my question is pretty obvious. How the hell do I parse strings using FormData with Axios in Vue.js? What have I done wrong to make this happen? God, thank anybody who can point out the issue in this. Thank you!
CodePudding user response:
$id = json_decode($_POST['id']);
It works if it is an integer because an integer is valid JSON.
It would also work if the string you were sending was null
, false
, "foo"
(yes, with the quotes), or any other valid JSON.
You are sending a FormData object which serializes to a multipart/form-data request body. This is not JSON
Do not try to process it as JSON.
Do not use file_get_contents("php://input")
; Do use $_POST
and $_FILES
Do not use json_decode
; Do just use the values from $_POST
and $_FILES
Aside: Do not specify 'Content-Type': 'multipart/form-data'
as this is missing the mandatory boundary
parameter. The browser will add the right Content-Type
header automatically when it receives the FormData object.