profilePic.move is not a function [AdonisJS] - file-upload

I am facing the error while trying to upload a file(image) via the form on AdonisJS (I referred to the official docs #AdonisJS4.1 File Uploads)
await profilePic.move(Helpers.tmpPath('uploads'), {
name: 'custom.jpg',
overwrite: true
})
if (!profilePic.moved()) {
console.log('file not moved')
}

Official Docs Here
HTML
<form method="POST" action="upload" enctype="multipart/form-data">
<input type="file" name="profile_pic" />
<button type="submit"> Submit </button>
</form>
JS
const Helpers = use('Helpers')
Route.post('upload', async ({ request }) => {
const profilePic = request.file('profile_pic', {
types: ['image'],
size: '2mb'
})
await profilePic.move(Helpers.tmpPath('uploads'), {
name: 'custom-name.jpg',
overwrite: true
})
if (!profilePic.moved()) {
return profilePic.error()
}
return 'File moved'
})

Related

data in Vue instance doesn't get updated after axios post response

I am writing a code piece to submit the html form data on a POST REST API. Using Vue.js and axios for that.
My Vue.js code is like this -
const app = new Vue({
el: "#main-div",
data() { return {
name: 'Please enter the name',
showEdit: true,
showResponse: true,
responseText: null
}
},
methods: {
savePerson: function () {
this.showEdit = false;
axios
.post('/api/person', {
name: this.name
})
.then(function (response) {
this.responseText = response.data.name+ ' added successfully.';
console.log(response);
console.log(response.data.name+ ' added successfully.');
})
.catch(function (error) {
this.responseText = error.message;
console.log(error);
});
}
}
}
)
And html -
<div id="main-div">
<h2> Fill out the details to create a Person</h2>
<div v-if="showEdit">
<form >
<div>
Name: <input v-bind:value = 'name' type="text" v-on:focus="name= ''" />
</div>
<div>
<button v-on:click="savePerson">Save</button>
</div>
</form>
</div>
<div v-if="showResponse">
<div><p>{{ responseText }}</p></div>
<div>
<button v-on:click="showEdit = true">Add one more person</button>
</div>
</div>
This code doesn't update responseText. That I can check in Vue plugin in browser.
Any idea what is not correct in my example?
You need to use an arrow function in the callback or else the function injects its own this context:
.then((response) => {
...
})
.catch((error) => {
...
})
Or you could use async/await:
async savePerson() {
this.showEdit = false;
try {
const response = await axios.post('/api/person', {
name: this.name
})
this.responseText = response.data.name+ ' added successfully.';
} catch(error) {
this.responseText = error.message;
}
}
to bind data with the input field you need to use v-model in the HTML and try to use the arrow function in the API call.

How I can upload files using Laravue with Dropzone

i'm trying to make work Laravue Dropzone, but I have'nt working yet
Here is the code:
<el-dialog :title="'Importar Bitacora'" :visible.sync="dialogFormVisible">
<div v-loading="weblogCreating" class="form-container">
<el-form ref="weblogForm" :rules="rules" :model="newBitacora" label-position="left" label-width="150px">
<div class="editor-container">
<dropzone id="CargarBitacora" url="/api/bitacora/importar" #dropzone-removedFile="dropzoneR(e)" #dropzone-error="dropzoneError" #dropzone-success="dropzoneS" />
</div>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button #click="dialogFormVisible = false">
{{ $t('bitacora.cancel') }}
</el-button>
<el-button type="primary" #click="handleUpload()">
{{ $t('bitacora.confirm') }}
</el-button>
</div>
</el-dialog>
<script>
import Dropzone from '#/components/Dropzone';
export default {
name: 'BitacoraList',
components: { Dropzone },
data() {
return {
files: [],
},
created() {
.. code here ..
},
methods: {
handleUpload(e) {
const formData = new FormData();
this.files.forEach(file => {
formData.append('files[]', file);
});
console.log(this.files);
},
}
};
</script>
I've tried to pass the files to handleUpload, but I can't make it work to the moment
I figured out how to upload files with dropzone, en the method handleUpload I just have to send the file to a post method in laravel backend who upload a temporary file
dropzoneR(file) {
var name = file.upload.filename;
fileResource.borrar(name).then(response => {
this.files.splice(this.files.indexOf(name), 1);
if (this.files.length < 1) {
this.btnUpload = true;
}
}).catch(error => {
console.log(error);
});
},
and returns an ok if it gets uploaded, then when I confirm thats the files I need up, other method in laravel backend who do what a want to do with the file if its an excel file (in mi case) upload the data to the database, or what ever I want. like this
async handleUpload(e) {
this.weblogCreating = true;
await bitacoraResource.store(this.files).then(response => {
this.$message({ message: 'Bitacoras importadas satisfactoriamente', type: 'success' });
this.files = '';
this.dialogImportVisible = false;
this.weblogCreating = false;
this.getList();
}).catch(error => {
this.$message({
message: 'Error importando las bitacoras ' + error.getMessage,
type: 'error',
});
this.weblogCreating = false;
console.log(error.message);
});
},

How To Correctly Bind Form in Vue & Vuex - Difference of v-model, :value & :value.sync

I'm fairly new to Vue & Vuex and am unsure on how to set up my form correctly.
<template>
<div>
<div v-if="error">{{error.message}}</div>
<form #submit.prevent>
<h1>Register</h1>
<input type="email" name="" id="" :value.sync="email" placeholder="Email">
<input type="password" :value.sync="password" placeholder="Password">
<button #click="signup">Submit</button>
Sign in
</form>
</div>
</template>
<script>
import {fireAuth} from '~/plugins/firebase.js'
export default {
data: () => ({
email: '',
password: '',
error: ''
}),
methods: {
signup() {
fireAuth.createUserWithEmailAndPassword(this.email, this.password).then(res => {
if (res) {
this.$store.commit('setCurrentUser', res.user)
this.$router.push('/')
}
}).catch(err => {
this.error = err
console.log(err)
})
}
}
}
</script>
At first I tried v-model to bind the form, it was throwing and error as I was mutating the store but I'm not storing email and password so I'm unsure how this is mutating the store? If I use :value or :value.sync then the email and password fields remain an empty string, so I'm not sure how to set up these correctly or how they differ from v-model
Edit: Adding my code from the store as requested
export const state = () => ({
currentUser: {}
})
export const mutations = {
setCurrentUser (state, obj) {
state.currentUser = obj
}
}
Vue.config.devtools = false
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data() {
return {
email: '',
password: ''
}
},
methods: {
signup() {
console.log(this.email) // email value
console.log(this.password) // password value
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="app">
<div>
<form #submit.prevent="signup">
<h1>Register</h1>
<input type="email" v-model="email" placeholder="Email">
<input type="password" v-model="password" placeholder="Password">
<input type="submit">
</form>
</div>
</div>
</body>
</html>
I think I have found the solution, it was the way in which I was trying to use firebase. I have used v-model, but am using a firebase method onAuthStateChanged, only if that is called will I change the store. So in my firebase.js I added
const fireAuth = firebase.auth()
const fireDb = firebase.database()
export { fireAuth, fireDb }
export default async ({ store }) => {
await asyncOnAuthStateChanged(store)
}
function asyncOnAuthStateChanged (store) {
return new Promise(resolve => {
fireAuth.onAuthStateChanged(user => {
resolve(user)
store.commit('setCurrentUser', JSON.parse(JSON.stringify(user)))
})
})
}

VueJS upload image with additional data

I am trying to upload image to the server and the same time to pass some additional data (in the same post request) using: VueJS 2 (CLI 3), axios, multer, sharp and I have NodeJS with MongoDB in the backend.
Front-end:
<form #submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="input">
<label for="name">Name: </label>
<input
type="text"
id="name"
v-model="name">
</div>
<div class="input">
<label for="last_name">Your last_name: </label>
<input
type="text"
id="last_name"
v-model="last_name">
</div>
<div class="input">
<label for="permalink">permalink</label>
<input
type="text"
id="permalink"
v-model="permalink">
</div>
<div class="input">
<label for="price">price</label>
<input
type="text"
id="price"
v-model="price">
</div>
<div class="input">
<label for="photo">photo</label>
<input
style="display: none"
type="file"
id="photo"
#change="onFileSelected"
ref="fileInput">
<div #click="$refs.fileInput.click()">Pick file</div>
</div>
<div class="submit">
<md-button type="submit" class="md-primary md-raised">Submit</md-button>
</div>
</form>
VueJS methods:
import axios from 'axios'
export default {
data () {
return {
name: '',
last_name: '',
permalink: '',
selectedFile: null,
url: null,
price: 0,
second: false
}
},
methods: {
onFileSelected (event) {
this.selectedFile = event.target.files[0]
this.url = URL.createObjectURL(this.selectedFile)
},
onUpload () {
const fd = new FormData()
fd.append('image', this.selectedFile, this.selectedFile.name)
axios.post('http...', fd, {
onUploadProgress: uploadEvent => {
console.log('Upload Progress ' + Math.round(uploadEvent.loaded / uploadEvent.total * 100) + ' %')
}
})
.then(res => {
console.log(res)
})
},
onSubmit () {
const fd = new FormData()
fd.append('image', this.selectedFile, this.selectedFile.name)
fd.append('data', this.name, this.last_name)
axios.post('http://localhost:7000/api/create-user', fd, {
onUploadProgress: uploadEvent => {
console.log('Upload Progress ' + Math.round(uploadEvent.loaded / uploadEvent.total * 100) + ' %')
}
})
.then(res => {
console.log(res)
if (res.data === 'ok') {
this.second = true
}
})
.then(
setTimeout(function () {
this.second = false
this.reset()
}.bind(this), 2000)
)
.catch(error => console.log(error))
}
}
}
NodeJS:
controller.postCreateUser = (req, res) => {
const sharp = require('sharp');
const fs = require('fs');
const folderImg = 'backend/uploads/';
console.log(JSON.stringify(req.body));
console.log(req.file);
res.send("ok");
};
The results of req.file is (which is good):
{ fieldname: 'image',
originalname: 'musk.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'backend/uploads/original/',
filename: 'musk-1545470459038.jpg',
path: 'backend\\uploads\\original\\musk-1545470459038.jpg',
size: 108787 }
The results of console.log(req.body) is
{"data":""}
The problem is here data has empty string and I don't receive any data. I need having the data to store to my database. How to do that?
If something isn't very clear to you, ask me for more details.
In your onSubmit method, you do this:
const fd = new FormData()
fd.append('image', this.selectedFile, this.selectedFile.name)
fd.append('data', this.name, this.last_name)
But FormData.append() expects these parameters:
name - The name of the field whose data is contained in value.
value - The field's value. This can be a USVString or Blob (including subclasses such as File).
filename Optional - The filename reported to the server (a USVString), when a Blob or File is passed as the second parameter.
The third parameter does not apply on this line: fd.append('data', this.name, this.last_name)
Instead, you can do either of these:
fd.append('data', `${this.name} ${this.last_name}`) // Send a single String
or
// Send both Strings separately
fd.append('name', this.name)
fd.append('last_name', this.last_name)
or
// Send the data as JSON
fd.append('data', JSON.stringify({name: this.name, last_name: this.last_name}))

How can I upload image to server using axios

I am trying to send a form along with an image. Note: I don't want to save the image in a database, I want to save it in a folder which I created on the server and just add a link of the image to the database.
From the server side I know how to handle this, but I don't know how to do this from font-end. With other words, how can I send the image using axios to the server.
<template>
<input type="text" class="form-control" id="specdesc" v-model="product.specdesc" name="specdesc" placeholder="Enter your name">
<input type="file" name="image" id="image" accept="image/*" >
<button type="submit" class="btn btn-sm btn-primary"#click.prevent="Submit()"> Submit</button>
</template>
<script>
export default {
name: 'Addproduct',
data(){
return{
image: '',
product:{
specdesc:'',
},
}
},
methods:{
Submit(){
var _this=this
// console.log(this.image)
console.log(this.selectedCategory.category_name)
var product = {
specification:this.product.specdesc,
imagename:this.image
}
this.$http.post('http://localhost:3000/api/companyproducts',product)
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log("error.response");
});
}
},
}
</script>
Now my question is how can I upload a image as well as the input name using axios. Moreover I want to use the same method i.e var product to send.
A standard (mostly) approach will be to split the logic in two, if you want to save the image path on your product, you firstly need to upload the photo to the server and return their path.
pseudo example:
component's data
{
imagePath: '',
productSpect: ''
}
``
``html
<input type="text" v-model="productSpect" />
<input type="file" #change="uploadImage" name="image" id="image" accept="image/*" >
<button type="submit" #click.prevent="submit"> Submit</button>`
``
**uploadImage method**
uploadImage (e) {
let img = e.target.files[0]
let fd= new FormData()
fd.append('image', img)
axios.post('/upload-image', fd)
.then(resp => {
this.imagePath = resp.data.path
})
}
**submit method**
submit () {
let data = {
imagePath: this.imagePath,
productSpect: this.productSpect
}
axios.post('/path/to/save', data)
}
**edited method to handle just only 1 image on the server**
Change the input `#change` to just save the img on a property under data():
<input type="file" #change="image = e.target.file[0]" name="image" id="image" accept="image/*" >
submit() {
let fd= new FormData()
fd.append('image', this.image)
axios.post('/upload-image', fd)
.then(resp => {
this.imagePath = resp.data.path
let data = {
imagePath: this.imagePath,
productSpect: this.productSpect
}
axios.post('/path/to/save', data)
})
}
There is nothing specific to Vue in this question. To send a POST request with axios, the easiest thing to do is to grab the formData of the html form and pass it as the data argument to Axios. To do this in Vue, just give your form tag a ref, then create a formData from the form.
<form ref="myForm">
// then in your method...
var myFormData = new FormData(this.$refs.myForm)
axios({
method: 'post',
url: 'myurl',
data: myFormData,
config: { headers: {'Content-Type': 'multipart/form-data' }}
})
for upload file I've used vuetify https://vuetifyjs.com/en/components/file-inputs/
<v-file-input
accept="image/png, image/jpeg, image/bmp"
placeholder="Pick an avatar"
prepend-icon="mdi-camera"
v-model="imageData"
></v-file-input>
<v-btn color="primary" #click="onUpload">Upload</v-btn>
in my vue method I have
onUpload() {
let formData = new FormData();
formData.append('file', this.imageData);
axios.post(
"/images/v1/upload"
,formData
,{headers: {"Content-Type": "multipart/form-data"}}
)
.then(response => {
//...
})
.catch(e => {
//...
})
}
Best regards!