How To Attach File On Axios Post Request In Vue - vue.js

Hello I am trying to attach file for axios.post however when I do a console.log() the formData is empty so here is what I am working with.
On my vue form
<form #submit.prevent="uploadTodos">
<div>
<input type="file" v-on:change="selectedFile($event)">
<label>Choose file</label>
</div>
<button type="submit">Submit</button>
</form>
Here is the data object
data() {
return {
file: null,
}
}
and method I have for the selectedFile on change event
selectedFile(event) {
this.file = event.target.files[0]
},
and here is the submit event method
uploadTodos() {
let formData = new FormData
formData.append('file', this.file)
this.$store.dispatch('uploadTodos', formData)
}
and here is the store method being dispatch
uploadTodos(context, file) {
console.log(file)
axios.post('/import', file,{ headers: {
'Content-Type': 'multipart/form-data'
}})
.then(response => {
console.log(response.data)
context.commit('importTodos', response.data)
})
.catch(error => {
console.log(error.response.data)
})
}
and when I console.log(file) I get the formData I created in the uploadTodos() method however it is empty, So I am trying to figure out why it is empty?
any help would be greatly appreciated

Related

Progress bar with Vue and Axios object

I would like to create an upload progress bar with Axios.
Everything is working fine with server sending and response.
The problem is that I don't know how to capture the progress percentage (which is correctly calculated) from my exported object.
My file upload.js:
import axios from 'axios'
const baseUrl = 'http://localhost:80/upload.php'
const config = {
Headers: {'Content-Type': 'multipart/form-data'},
onUploadProgress: progressEvent => {
return parseInt(Math.round((progressEvent.loaded / progressEvent.total) * 100))
}
}
export default {
send (data) {
return axios.post(baseUrl, data, config)
}
}
My Vue component:
<template>
<div>
<label>File:</label>
<input type="file" id="file" ref="file" #change="changeFile()" />
<button #click="submit()">Upload</button>
<br />
<progress max="100" :value.prop="uploadPercentage"></progress>
</div>
</template>
<script>
import upload from '../services/upload.js'
export default {
name: 'Upload',
data: () => ({
file: null,
uploadPercentage: 0
}),
methods: {
submit () {
const formData = new FormData()
formData.append('file', this.file)
upload.send(formData)
.then(res => {
console.log(res.data)
})
.catch(() => {
console.log('Failure')
})
},
changeFile () {
this.file = this.$refs.file.files[0]
}
}
}
</script>
How to retreive, from the component submit method, the info sent by the onUploadProgress in order to update the data uploadPercentage?
Thanks.
Regards.
You need to pass a function to your send operation that will be called later.
See example below
const config = {
Headers: {'Content-Type': 'multipart/form-data'},
onUploadProgress: progressEvent => {
var progress= parseInt(Math.round((progressEvent.loaded / progressEvent.total) * 100));
if (config.onProgress)
config.onProgress(progress);
}
}
export default {
send (data, onProgress) {
config.onProgress= onProgress;
return axios.post(baseUrl, data, config)
}
}
Then you upload code will be
upload.send(formData,(pogress)=>{
// Update your uploadPercentage here
})
.then(res => {
console.log(res.data)
})
.catch(() => {
console.log('Failure')
})

vue: V-input-file is not of type ‘HTMLFormElement’ error

on Vue adding selected file to FormData ends with error in both v-input-file and input type=‘file’.
error massage:
Failed to construct ‘FormData’: parameter 1 is not of type ‘HTMLFormElement’.
<template>
<Layout v-if="$store.state.user">
<v-form
id='myform'
name='myForm'
class='myform'
ref="form"
lazy-validation
enctype="multipart/form-data"
method="POST"
>
<!-- FILE UP-LOAD -->
<template>
<v-file-input
:rules="rules_fileInput"
accept="image/png, image/jpeg, image/bmp"
show-size
counter
label="PNG, JPEG, BMP"
placeholder="Pick an image"
prepend-icon="mdi-camera"
#change="onFilePicked"
/>
</template>
<v-btn dark #click="submitForm">
Save
</v-btn>
</v-form>
</Layout>
</template>
<script>
export default {
data: () => ({
imageUpload: null,
}),
methods: {
onFilePicked(file) {
this.imageUpload = file;
},
async submitForm() {
console.log('this.imageUpload:', this.imageUpload) // showing file
//const headersImg = { headers:{ 'Content-Type':'multipart/form-data'}};
const { data } = await axios.post(
url,
new FormData(
`files.${this.imageUpload.name}`,
this.imageUpload,
this.imageUpload.name
)
);
}
enter image description here
the image above clearly some file data.
if i will try to append FormData like so:
async submitForm() {
const formData = new FormData();
formData.append(
`files.${this.imageUpload.name}`,
this.imageUpload,
this.imageUpload.name
);
//console.log('...formData:', ...formData);
const urlLocal = 'http://localhost:1337/upload';
const urlLive = 'http://www.events-pr-server.ml/upload';
// client in netlefy, server in heroku with: Allow all Origin - for this demo
try {
const { data } = await axios({
method: 'post',
url: urlLive,
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
// 'Access-Control-Allow-Origin': '*',
},
});
results as: Files are empty
tatusCode: 400, error: “Bad Request”, message: “Bad Request”,…}.
data: {errors: [{id: “Upload.status.empty”, message: “Files are
empty”}]}.
enter image description here
enter image description here
Based on your last comment, i created a codepen to check the issue.
There is no HTMLFormElement error which i encountered, check below code pen
https://codepen.io/kurtesy_/pen/MWJBwQX?editors=1111
Next to Post a formData using axios use the below protocol, you need to specify "Content-Type": "multipart/form-data"
axios({
method: "post",
url: "your_url",
data: formData,
headers: { "Content-Type": "multipart/form-data" },
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});

How to upload multiple image in Vue.JS and axios (Vuex)

all day I’m trying to solve the problem with multi-upload images
In console log im see all the data but when I try to write this data to a variable im get empty array
If someone have info about solve this problem I'll be very grateful
This is my code in Vue component for upload images
<div class="card-body">
<form>
<vue-upload-multiple-image
#upload-success="uploadImageSuccess(id)"
#before-remove="beforeRemove"
#edit-image="editImage"
:data-images="images"
idUpload="myIdUpload"
editUpload="myIdEdit"
></vue-upload-multiple-image>
</form>
</div>
This is my data in Vue Component
data()
{
return{
images: [],
}
},
This is my function from upload images in Vue Component
uploadImageSuccess(id, formData, index, fileList) {
this.images = fileList;
console.log(formData)
console.log(index)
console.log(fileList)
this.addNewGallery({id, data: this.images});
},
This is my code from Vuex Store from upload images
async addNewGallery(ctx, {id, data})
{
return new Promise((resolve, reject) => {
axios({
url: '/gallery/' + id,
method: 'PUT',
data: data,
})
.then((resp) => {
console.log(resp)
})
.catch((error) => {
console.log(error)
reject(error)
})
})
}
This is my code from Console tab in browser
[{…}, ob: Observer]
0:
name: "IPhoneX.png"
path: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAC7gA"
highlight: 1
default: 1

Quasar Framework Uploader with axios

A question about the quasar framework uploader component.
I need to post the images to a URL that will rename the uploaded file and return the full path.
I'm using the upload-factory and axios
But I'm having problems understanding exactly how to pass the file to axios as if it was just an input type file.
Basically I need to make it as If I'm sending a form with a single input file like this:
<input type="file" name="banner">
This is the component:
<q-uploader
url=""
extensions=".gif,.jpg,.jpeg,.png"
:filter="filterFiles"
:upload-factory="uploadFile" />
This is the upload method, but I keep getting an error response from the server.
uploadFile (file, updateProgress) {
const formData = new FormData()
formData .set('banner', file)
var headers = {
'Content-Type': 'multipart/form-data'
}
axios.post('http://someurl/uploadFile', formData , headers)
.then(function (response) {
console.log(response)
})
.catch(function (response) {
console.log(response)
})
}
If I post a plain html form with method="post" enctype="multipart/form-data" and a
<input type="file" name="banner">
I get my OK response from the server with the processed/uploaded image URL
I have successfully done uploading of the file to python API.
V1 Update
Use #added -> function(files) method.
Also extensions property is removed now use accept
This is the component:
<q-uploader
url=""
extensions=".gif,.jpg,.jpeg,.png"
#add="file_selected"
/>
<q-btn #click="uploadFile()">Upload</q-btn>
Data:
data() {
return {
selected_file:'',
check_if_document_upload:false,
}
}
Methods
file_selected(file) {
this.selected_file = file[0];
this.check_if_document_upload=true;
},
uploadFile() {
let fd = new FormData();
fd.append("file", this.selected_file);
axios.post('/uploadFile', fd, {
headers: { 'Content-Type': undefined },
}).then(function(response) {
if(response.data.ok) {
}
}.bind(this));
}
This is working fine for me.
I have successfully done direct uploading of the file on a button click to python API. But in vue3 and Quasar 2 with some additional formData. Thought might be helpful
This is component:
<q-btn
label="Upload"
#click="openFilePicker"
/>
<q-uploader
ref="uploadFile"
class="hidden"
accept=".jpg, .jpeg, .png"
#added="uploadFileFn"
/>
Setup:
setup() {
return {
uploadFile: ref(null),
}
},
Methods:
openFilePicker() {
this.$refs.uploadFile.pickFiles();
},
uploadFileFn(file) {
this.uploadFile = file[0];
let fd = new FormData();
fd.append("file", this.uploadFile);
fd.append("id", "1");
fd.append("name", "test_user");
this.$axios.post('/upload_file_with_additional_form_data', fd, {
headers: {'Content-Type': undefined},
}).then(
function (response) {
if (response.data.success) {
console.log(response)
}
}.bind(this))
}
This is working fine for me.

vue2 data change not updating view

I have a simple file upload component FileUpload.vue
<template>
<div>
<input type="file" name="file" id="file" v-on:change="handleFileUpload()" ref="file">
<button class="btn shadow-lg first" #click="addFiles()">SELECT FILE</button>
<button class="btn shadow-lg" v-on:click="handleSubmit()">UPLOAD</button>
<p> {{uploadPercentage}} </p>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'FileUpload',
data() {
return {
file: '',
uploadPercentage: 0
}
},
methods: {
handleFileUpload: () => {
this.file = document.getElementById('file').files[0];
},
addFiles: () => {
document.getElementById('file').click();
},
handleSubmit: () => {
let formData = new FormData();
formData.append('file', this.file);
axios.post('/file/create',
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: (progressEvent) => {
console.log(this.uploadPercentage);
this.uploadPercentage = parseInt(Math.round(progressEvent.loaded * 100 / progressEvent.total));
}
}
)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
})
}
}
}
</script>
The data uploadPercentage is initialized to 0. As the file upload starts, the uploadPercentage value changes in the onUploadProgress method.
If I console log uploadPercentage, it shows the changes in the value. It goes from 0 to 100.
console.log(this.uploadPercentage)
But in my view, uploadPercentage never changes. It always shows the initial value 0.
<p> {{uploadPercentage}} </p>
What am I doing wrong?
Thanks in advance.