How can I upload image to server using axios - vue.js

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!

Related

how to upload complete excel file into server using vuejs

Code
template
<template>
<div id="app">
<input type="file" #change="onChange" />
</div>
</template>
export default {
name: "App",
methods: {
async onChange(event) {
const headers = {
'Content-type': 'multipart/form-data'
},
const response = await.post('http://localhost:3030/api/new/post', event.target.files[0], headers);
console.log(response);
},
}
};
I would like to upload file as it is through api, I tested through postman it does work. How can I upload it via VueJS. can anyone suggest.
Thank You
You can use FormData to send files to the server.
<template>
<div id="app">
<input type="file" #change="onChange" />
</div>
</template>
<script>
export default {
name: "App",
methods: {
async onChange(event) {
const formData = new FormData();
formData.append("file", event.target.files[0]);
const response = await axios.post("xyzzy.com", formData);
console.log(response);
}
}
};
</script>

Uploading files to Google Cloud Buckets using Rest API POST

I searched around but I couldn't find anything useful about this.
I'm trying to upload a file to a google cloud bucket in my project using REST APIs, but all i am obtaining is a binary file in the bucket, and not the actual file.
Uploading using curl as explained in the Documentation works fine and, e.g., i can upload a png to my bucket.
I am using Vue.js and axios to make the request.
This is the code for the form:
<template>
<div>
<div id="form">
<form #submit.prevent="postFiles" enctype="multipart/form-data">
<input type="file" #change="previewFiles" multiple />
<input type="submit" value="Send file" />
</form>
</div>
</div>
</template>
<script>
export default {
name: "InsertFile",
data() {
return {
file: "",
};
},
methods: {
previewFiles(event) { //I use this just for the debug
console.log(event.target.files);
this.file = event.target.files;
},
postFiles(){
this.$emit('insert-file',this.file);
}
},
};
</script>
This is the code for the view
<template>
<div class="upload">
<h1>Here you can upload your files</h1>
<InsertFile #insert-file="postFile" />
</div>
</template>
<script>
import InsertFile from "../components/InsertFile";
import axios from "axios";
let token='exampletoken'
let config = {
headers: {
'content-type': 'multipart/form-data',
Authorization: "Bearer " + token,
},
};
let url =
"https://storage.googleapis.com/upload/storage/v1/b/bucketURL/o?uploadType=media&name=foo.png";
export default {
components: {
InsertFile,
},
methods: {
postFile(path) {
let bodyFormData = new FormData();
bodyFormData.append("image", path[0]);
console.log(bodyFormData);
axios
.post(url, bodyFormData, config)
.then((response) => {
console.log("Response", response.data);
})
.catch((e) => {
console.log("Error: ", e.response.data);
});
},
},
};
</script>
From this code i obtain a file of type multipart/form-data in the bucket, how can i upload it as a png (or any kind of file)?
[EDIT]
This is the form right now
<template>
<div>
<div id="form">
<form #submit.prevent="postFiles" enctype="multipart/form-data">
<input type="file" #change="previewFiles" multiple />
<input type="hidden" name="Content-Type" value="image/png">
<input type="submit" value="Send file" />
</form>
</div>
</div>
</template>
This is the method
<script>
import InsertFile from "../components/InsertFile";
import axios from "axios";
let url =
"https://storage.googleapis.com/upload/storage/v1/b/myBucket/o?uploadType=media&name=prova.png";
export default {
components: {
InsertFile,
},
methods: {
postFile(path) {
console.log(path);
let bodyFormData = new FormData();
bodyFormData.append("file", path[0]);
bodyFormData.append("content-type", "image/png");
console.log(bodyFormData);
let token ='mytoken'
let config = {
headers: {
Authorization: "Bearer " + token,
},
};
axios
.put(url, bodyFormData, config)
.then((response) => {
console.log("Response", response.data);
})
.catch((e) => {
console.log("Error: ", e.response.data);
});
},
},
};
</script>
Within the multipart data you need to send the mime type as a content-type.
For example, with a JPEG you would send Content-Type: image/jpeg
Without this, the upload assumes that the file type is the default of being binary data not an image.
In your link to the docs you provided, take a look at this OBJECT_CONTENT_TYPE part.
To quote their documentation:
The MIME type of the file you are uploading via the form. If you do not specify a content type, the Cloud Storage system defaults to application/octet-stream when it serves the content.
If you are able to, I'd recommend installing and using the storage part of the official NodeJS SDK and following this example here: https://cloud.google.com/storage/docs/uploading-objects#storage-upload-object-nodejs
This should be a lot more robust and provide an immediately functioning example.
It will also make it a lot easier to utilise other functions of the API such as list or delete operations.

How to update Image in vue

I'm a newbie in vue, I need help to update image, I'm using vform, in below onFileSelected function responsible creating and updating image, I'm successfully creating data with image, but now I'm stack in update the image, here is my code with form structure
Form
<form #submit.prevent="editMode ? update() : store()">
<div class="form-group">
<label for="image" class="font-weight-bold">Image</label>
<input class="form-control" type="file"
:class="{ 'is-invalid': form.errors.has('image') }"
name="image" id="image" accept="image/*"
#change="onFileSelected">
<has-error :form="form" field="image"></has-error>
</div>
</form>
I'm storing like this
onFileSelected(event) {
let file = event.target.files[0];
this.form.image = file;
},
store() {
this.$Progress.start();
this.form.busy = true;
this.form.post('/api/students', {
transformRequest: [function (data, headers) {
return objectToFormData(data)
}],
}).then(response => {
//......
}),
My edit code is
edit(student) {
this.editMode = true;
this.clearForm();
this.form.fill(student);
$('#modal').modal('show');
},
update() {
this.$Progress.start();
this.form.busy = true;
this.form.patch('/api/students/' + this.form.id)
.then(response => {
//.........
})
.catch(e => {})
},
I think your issue is that while your data is updating the render is not. For this you can put a key attribute (with some number or id) on the element that contains the image and then inside the update function once updated change the key like: forceReloadKey++ this will force the component to rerender and update.
Like so:
<form :key="reloadKey" #submit.prevent="editMode ? update() : store()">
...
update() {
...
this.reloadKey++
...

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

Upload files using Vuejs with Axios

I work in the project with vuejs and bootsrapt-vue and I want to upload any type of file(picture, pdf ..etc) by axios library.
When I try to upload, nothing is uploading to the backend. Can some one please look in my code and tell what I'm doing wrong?
I'm pretty new into coding.
Here is my code:
`
<template> <b-container fluid>
<h4>Images page</h4>
<!-- <b-form-file action="" v-model="image" plain></b-form-file> -->
<b-form action="" method="post" v-model="image" enctype="multipart/form-data">
<h2>Select image to upload:</h2>
<input type="file" name="fileToUpload" id="fileToUpload">
<b-button type="submit" name="submit" variant="success" v-on:click="uploadImage">Upload image</b-button>
</b-form>
</b-container>
</template>
<script>
// eslint-disable-next-line
/* eslint-disable */
export default {
name: 'imagesPage',
data() {
return {
images: [],
image: []
}
},
methods: {
uploadImage(evt) {
evt.preventDefault()
var data = new FormData();
data.append('image', document.getElementById('fileToUpload').files[0])
var token = sessionStorage.setItem('token', data, null)
window.API.post('https://192.168.56.101:8080/images/' + token, data, null)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(JSON.stringify(error))
})
console.log('blabla')
// this.template.push({
// image_id: ''
// })
}
}
}
</script>
`