Quasar Framework Uploader with axios - vue.js

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.

Related

How to use mocking for test uploading file with jest

I am developing a system with nuxt js and jest that in part of that I want to upload an image.
Here's my html code:
<input
id="photo"
ref="photo"
type="file"
name=""
class="form-control d-flex"
#change="uploadPhoto"
>
Here's my uploadPhoto function in nuxt js:
uploadPhoto () {
const file = this.$refs.photo.files[0]
// upload photo
const formData = new FormData()
formData.append('photo', file)
const returnedData = await this.$axios.$post('/api/photo/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
The question is:
How may I mock uploading photo in jest to test my code?
My jest code is something like this:
test('uploading photo test', () => {
wrapper = mount(UploadPhotoComponent, {
stubs: {
NuxtLink: true
},
mocks: {
$auth: {
loggedIn: true,
$storage: {
_state: {
'_token.local': 'api bearer token'
}
}
},
$axios: {
$post: jest.fn(() => {
return Promise.resolve({
status: 200,
message: 'photo was uploaded successfully.',
entire: []
})
})
}
}
})
})
I don't know how to test uploading file in jest using mocks.
Can anyone help me?
Finally, I have realized how to do that. First of all generate an image blob and file:
import fs from 'fs';
import path from 'path';
const dummyImgData = fs.readFileSync(
path.join(__dirname, '../../libs/dummy-img-2.jpeg')
);
const fbParts = [
new Blob([dummyImgData], {
type: 'image/jpeg'
}),
'Same way as you do with blob',
new Uint16Array([999999999999999])
];
const fbImg = new File(fbParts, 'sample.png', {
lastModified: new Date(2020, 1, 1),
type: 'image/jpeg'
});
And after assign it to $refs object:
wrapper.vm.$refs = {
photo: {
files: [
fbImg
]
}
}

How to get the data inside of CSV file

Good day,
I'm working on a project that have an import functionality. How can I retrieve the data inside of the csv file?. It is possible to retrieve it in front end or should I use axios.post?
Here is my code so far:
<input
type="file"
id="files"
style="display: none;"
accept=".csv"
ref="file"
v-on:change="handleFileUpload()"
/>
<button #click="onImport"> Import </button>
In my method :
data: {
file: '',
},
methods: {
onImport() {
$('#files').click();
},
handleFileUpload() {
this.file = this.$refs.file.files[0];
let formData = new FormData();
formData.append('file', this.file);
}
Thank you in advance for the help
You can use FileReader like so:
async handleFileUpload() {
this.file = this.$refs.file.files[0];
const reader = new FileReader();
reader.readAsText(this.file);
reader.onload = () => {
console.log(reader.result); // contains the file content as a string
};
reader.onerror = () => {
console.log(reader.error);
};
const formData = new FormData();
formData.append('file', this.file);
// Send your file to your server and retrieve the response
const res = await axios.post('https://example.com/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
It works on all major browsers also.

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);
});

Carrierwave: upload an image from vue front to rails api

I am not sure how to make the axios post for the image.
This is what my json object looks like.
{
"id":20,
"title":"pineapple",
"text":"pineapple",
"date":null,
"created_at":"2019-03-23T01:42:48.142Z",
"updated_at":"2019-03-23T01:42:48.142Z",
"image":{
"url":null
}
}
This is my image input from the Vue form.
<input type="file"
id="file"
ref="myFiles"
class="custom-file-input"
#change="takeFile"
multiple>
Here is me trying to make sense of it.
export default {
data() {
return {
blog: {
title: '',
content: '',
link: ''
}
}
},
methods: {
submitArticle(blog) {
console.log('blog.link', blog.link)
axios.post('http://localhost:3000/articles', {
title: blog.title,
text: blog.content,
image: {
url: blog.link
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},
takeFile(event) {
console.log(this.$refs.myFiles.files);
this.blog.link = this.$refs.myFiles.files
}
}
}
Here is a link to the file in my repo.
First this.$refs.myFiles.files returns an array of files. Change your method like this to set the file to blog.link:
takeFile(event) {
this.blog.link = this.$refs.myFiles.files[0]
}
Now to send file in your post request, you should use FormData:
submitArticle(blog) {
let formData = new FormData()
formData.append("article[title]", blog.title)
formData.append("article[text]", blog.content)
formData.append("article[image]", blog.link)
axios.post('http://localhost:3000/articles', formData, {
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
console.log(response)
}).catch(function (error) {
console.log(error)
})
},

How To Attach File On Axios Post Request In Vue

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