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.
Related
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>
I am creating a simple to do list and using Json server as a mock data base. I am trying to add a delete button that will delete the goals that have already added to the Vue application.
This is my main app
<template>
<h1>To Do List </h1>
<addProject />
<div v-for="newGoal in newGoals" :key="newGoal.id" class = 'newGoal'>
<li >{{newGoal.goal}} <deleteGoalVue /> </li>
</div>
</template>
<script>
import addProject from './components/addProject.vue';
import deleteGoalVue from './components/deleteGoal.vue';
export default {
name: 'App',
components: { addProject, deleteGoalVue },
data(){
return {
newGoals: [],
}
},
mounted() {
fetch('http://localhost:3000/newGoals')
.then(res => res.json())
.then(data => this.newGoals = data)
.catch(err => console.log(err.message))
}
}
This is my add project/goal component
<template>
<form #submit.prevent="handleSubmit">
<h3><div class= instructions >Type in your goal for the day</div></h3>
<input type="text" v-model="goal" placeholder="Your goal">
<input type="submit" value="Add Goal" #click="storeGoal" >
</form>
</template>
<script>
export default {
props: ['project'],
data (){
return{
goal: "",
}
},
handleSubmit(){
let project = {
goal: this.goal,
}
fetch('http://localhost:3000/newGoals', {
method: 'POST',
headers: { 'Content-Type' : 'application/json' },
body: JSON.stringify(project)
})
}
}
And this is my Delete Goal component
<template>
<button #click ="deleteGoal" >Delete Goal</button>
</template>
<script>
export default {
methods: {
deleteGoal() {
fetch('http://localhost:3000/newGoals', { method: 'DELETE'})
}
}
}
</script>
The error that I am getting when I press the 'Delete Goal' button says
DELETE http://localhost:3000/newGoals 404 (Not Found)
I've been trying to post a file with axios to my database.
<template>
<div>
<v-file-input
v-model="file"
label="File input"
id="file"
ref="file"
>
</v-file-input>
<button v-on:click="submitFile()">Submit</button>
</div>
</template>
export default {
name: "Test",
data() {
return {
file: null,
}
},
methods: {
submitFile() {
let formData = new FormData();
formData.append('file', this.file);
axios.post('https://test_file_create/', formData).then(function() {
console.log('SUCCESS!!');
}).catch(function() {
console.log('FAILURE!!');
});
},
},
}
but the problem is in my database i got my file column null it seems it can't post the file although it return "SUCCESS!!" in submitFile function.
can someone please tell me how to solve this problem.
You've made a couple of mistakes here so from most severe to least...
The <v-file-input> component binds the selected file to its model but you are using the handleFileUpload() method to set your file property to the component itself (via $refs).
Try this instead, using v-model with your file property initialised to null instead of an empty string (which doesn't make sense for a File object)
<v-file-input
v-model="file"
label="File input"
id="file"
ref="file"
></v-file-input>
export default {
name: "Test",
data: () => ({ file: null }),
// etc
}
When sending a FormData instance from the browser, do not manually add the content-type header. FormData also requires special mime-boundary tokens which should be handled automatically
axios.post("https://test_file_create/", formData).then(res => ...)
You should only have one root element in your template. <div> is a popular choice
<template>
<div>
<v-file-input
v-model="file"
label="File input"
id="file"
ref="file"
></v-file-input>
<button :disabled="!file" type="button" #click="submitFile">Submit</button>
</div>
</template>
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!
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>
`