I'm using Quasar framework and Vue
I have input element that gets picked image after that I send It to servlet where I process that image and storing in a folder.If It was successfully I send simple message which will be displayed on page.Servlet works fine, I only need to know how to set image If response was without error.
<div id="q-app">
<input type="file" id="file"
ref="file" accept=".jpg, .jpeg, .png"
style="display:none"
#change="handleFileUpload()"/>
<div class="q-ma-md row justify-start">
<div class="col-auto">
<q-btn style="width:1000px;height:1000px;" #click="tclick">
<q-img height="100%" width="100%" :src="imageSrc">
</q-img>
</q-btn>
</div>
</div>
<div class="col-auto">
<q-btn class="q-ma-md" size="md" #click="submitFile()" color="primary" label="changeProfilePicture"></q-btn>
</div>
</div>
And javascript
I have methods that catch the selected image and send it to the servlet
<script>
new Vue({
el: '#q-app',
data () {
return {
file: '',
imageSrc:'${pageContext.request.contextPath}/images/profile.jpg',
}
},
methods:{
tclick(){
this.$refs.file.click()
},
handleFileUpload(){
this.file = this.$refs.file.files[0];
},
submitFile(){
let formData = new FormData();
formData.append('file', this.file);
axios.post( "${pageContext.request.contextPath}"+"/hello-servlet",
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(response => {
this.$q.notify({
type: 'positive',
message: response.data,
position:'center',
icon: 'check'
})
}).catch(error => {
console.log(error);
})
},
},
})
</script>
How can I set picked image to q-img tag?
Related
I'm trying to send file from vue-page to server. For this I use:
FileFrom component:
<template>
<div class="FileForm" v-bind:name="name">
<label class="FileFormLabel">
{{ name }}:
<input type="file" files="files" v-on:change="fileUpload" v-bind:name="name"/>
</label>
<button class="SubmitBtn" v-on:click="submit">
Submit
</button>
</div>
</template>
<script>
export default {
name: 'FileForm',
props: ["value", "name"],
data: function() {
return {
files: [],
}
},
methods: {
fileUpload: function(event) {
this.$emit("upload", [event.target.files[0]])
},
submit: function() {
this.files = []
this.$emit("submit")
},
},
}
</script>
Page:
<template>
<Container>
<div class="content">
<h1>
Upload files
</h1>
<div class="forms">
<FileForm v-bind:files="files['Model']" name="Model" v-on:upload="upload_model" v-on:submit="submit_model">
</FileForm>
</div>
</div>
</Container>
</template>
<script>
import axios from 'axios'
import Container from '#/components/Container.vue'
import FileForm from '#/components/FileForm.vue'
export default {
name: 'App',
data: function() {
return {
files: {},
}
},
components: {
Container,
FileForm
},
methods: {
upload_model: function(file) {
this.files['Model'] = file
},
submit_model: function() {
let formData = new FormData();
formData.append('Model', this.files['Model']);
axios.post('http://' + document.location.host + '/api/upload_model', formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
})
}
},
}
</script>
But sending request looks like this:
-----------------------------316537648527426258472746653245
Content-Disposition: form-data; name="Model"
[object File]
-----------------------------316537648527426258472746653245--
A file is not sent as file but as string "[object File]".
As far as I understand the problem is that FormData.append converts all non-Blob(or File) objects to string and this.files['Model'] is not this one. It is proxy object which Vue.js uses for reactivity.
How can I take the internal object from this proxy and use it for sending?
I changed
formData.append('Model', this.files['Model']);
to
formData.append('Model', this.files['Model'][0]);
in page code.
And now it works fine. I don't know, is it the way to get needed value from proxy or I just returned array of files instead of single file somewhere in my code, but it helped.
Javascript Vue: Where does the variable e in onFileChange(e) originate?
In the following code, there is a variable e in onFileChange(e), where does it originate? It is never declared or imported in the code, so how can it be valid?
Any help would be greatly appreciated.
<template>
<div class="container" style="margin-top: 50px;">
<div class="text-center">
<h4>File Upload with VueJS and Laravel</h4>
<br />
<div style="max-width: 500px; margin: 0 auto;">
<div v-if="success !== ''" class="alert alert-success" role="alert">
{{success}}
</div>
<form #submit="submitForm" enctype="multipart/form-data">
<div class="input-group">
<div class="custom-file">
<input
type="file"
name="filename"
class="custom-file-input"
id="inputFileUpload"
v-on:change="onFileChange"
/>
<label class="custom-file-label" for="inputFileUpload"
>Choose file</label
>
</div>
<div class="input-group-append">
<input type="submit" class="btn btn-primary" value="Upload" />
</div>
</div>
<br />
<p class="text-danger font-weight-bold">{{filename}}</p>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log("Component successfully mounted.");
},
data() {
return {
filename: "",
file: "",
success: ""
};
},
methods: {
onFileChange(e) {
//console.log(e.target.files[0]);
this.filename = "Selected File: " + e.target.files[0].name;
this.file = e.target.files[0];
},
submitForm(e) {
e.preventDefault();
let currentObj = this;
const config = {
headers: {
"content-type": "multipart/form-data",
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]')
.content
}
};
// form data
let formData = new FormData();
formData.append("file", this.file);
// send upload request
axios
.post("/store_file", formData, config)
.then(function(response) {
currentObj.success = response.data.success;
currentObj.filename = "";
})
.catch(function(error) {
currentObj.output = error;
});
}
}
};
</script>
That declaration is triggered by your template, where you are binding change event to the method. The whole event as parameter gets passed to the method, Refer this section of Vue docs for better information https://v2.vuejs.org/v2/guide/events.html#Method-Event-Handlers
When a variable is called e it is usually the event. You can always console.log(e) and read its properties in the browser console.
But according to this example e is the file that is uploaded:
methods: {
thumbUrl (file) {
return file.myThumbUrlProperty
},
onFileChange (file) {
// Handle files like:
this.fileUploaded = file
}
}
onFileChange(e) has e as event related to the dom. Since while assigning the function in html if there is no parameter passed, the event as a parameter is automatically passed by javaScript.
The declaration onFileChange(e) {
declares a function with the name onFileChange that takes a single parameter e. That is what introduces the variable into the function body.
I am using ElementUi uploader and i need to send my file with the rest of my form data, but it doesn't seem to send right details of photo to back-end:
Screenshots
Console log when i select an image
Data that sent to back-end
Code
photo input
<el-upload
action="#"
:limit="1"
:multiple="false"
:on-change="photoChanged"
:on-exceed="handleExceed"
list-type="picture-card"
:on-remove="handleRemove"
:on-preview="handlePictureCardPreview"
:before-remove="beforeRemove"
:auto-upload="false">
<i slot="default" class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
Script
export default {
data() {
return {
dialogImageUrl: '',
dialogVisible: false,
form: {
name: '',
slug: '',
price: '',
new_price: '',
sku: '',
qty: 1,
active: '',
photo: '',
shortDesc: '',
longDesc: '',
region: '',
date1: '',
date2: '',
type: [],
tags: [],
brand_id: '',
categories: [],
resource: '',
user_id: ''
}
}
},
methods: {
onSubmit(e) { //send data to back-end
e.preventDefault();
axios.post('/api/admin/products/store', this.form)
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
})
},
handleRemove(file) {
this.form.photo = ''; // remove photo from from when it's removed
},
photoChanged(file, fileList){
this.form.photo = file.raw; // add photo to form when it's selected
console.log('file', file) // screenshot 1
console.log('raw', file.raw) //screenshot 2
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
handleExceed(files, fileList) {
this.$message.warning(`The limit is 1, you selected ${files.length} files this time, add up to ${files.length + fileList.length} totally, remove old image and try again.`);
},
beforeRemove(file) {
return this.$confirm(`Cancel the transfert of ${ file.name } ?`);
}
},
}
</script>
Any idea?
I have used FormData to send the photo or document to the server.
JavaScript FormData
<form id="myForm" name="myForm">
<div>
<label for="username">Enter name:</label>
<input type="text" id="username" name="username" v-model="imageData.name">
</div>
<div>
<label for="useracc">Enter account number:</label>
<input type="text" id="useracc" name="useracc" v-model="imageData.account">
</div>
<label for="userfile">Upload file:</label>
<input type="file" id="userfile" name="userfile">
</div>
<input type="submit" value="Submit!">
</form>
export default {
data() {
return {
imageData: {}
}
},
methods: {
uploadImageToServer() {
// 1.Save the form Data and return the new id to save the image
axios.post('/api/admin/products/store', this.imageData)
.then(res => {
if(res.id) {
//2. Save the image to id
let formData = new FormData();
let file = document.getElementById('userfile');
formData.append('file', file)
axios.post('/api/admin/products/image/{id}', formData)
.then(res => {
console.log(res)
})
}
})
.catch(err => {
console.log(err)
})
}
}
}
Here,
Both form data & file data maynot be send in single requst.
1. Saving the form data and return the id.
2. Saving the image data to the id.
Replace the html with 'element-ui' syntax. Ensure that your rest api receives the form data as the input.
convert your file to base64
when you select an image, use code below
onImageChange() {
let file = this.form.photo
if (file == '')
return;
this.createImage(file);
}
createImage(file) {
let reader = new FileReader();
let el = this
reader.onload = (e) => {
el.form.photo = e.target.files[0];
};
reader.readAsDataURL(file);
},
attach onImageChange function in your input file
Solved
Well I have decided to give up on sending image with rest of data to backend and upload image first with action="#" in my input and in return i get file name in my form and just send the file name with rest of form instead of sending image file.
<el-upload
action="/api/upload"
:on-success="handleAvatarSuccess"
.....>
methods: {
handleAvatarSuccess(res, file) {
this.form.photo = res.data;
},
}
So it sends my file to back-end as soon as it's selected and set the name of stored file in my form.photo and that name will be send with rest of my form inputs.
Hope it could be useful to others as well.
Upload images and form content? How to upload? The idea is to upload it to the client and then upload it to the server along with the form content, right?
I want to upload the form content and the image to the server when I click submit, instead of uploading the image separately when I upload the image.
But I don't know how to upload at the same time. Can you help me?
<template>
<form>
<input type="text" v-model="test">
<img :src="previewImage" class="uploading-image" />
<input type="file" accept="image/jpeg" #change=uploadImage>
<input type="submit"></input>
</form>
</template>
export default {
data(){
return{
previewImage:null,
test: ''
}
},
methods:{
uploadImage(e){
const image = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(image);
reader.onload = e =>{
this.previewImage = e.target.result;
console.log(this.previewImage);
};
const URL = 'http://xxxx';
let data = new FormData();
data.append('name', 'my-picture');
data.append('file', event.target.files[0]);
let config = {
header : {
'Content-Type' : 'image/png'
}
}
axios.put(URL, data,config).then(response => {
console.log('image upload response > ', response)
})
}
}
You need to add this to the form
<form #submit.prevent="uploadImage">
<input type="text" v-model="test">
<img :src="previewImage" class="uploading-image" />
<input type="file" accept="image/jpeg" >
<input type="submit"></input>
</form>
I'm trying to upload multiple files to server.
The file is being stored in a variable.
When I click upload the client is sending that variable empty.
Here is my html
<div class = "control-group form-group col-md-12"
ng-class = "{'has-error':newAsset.OSGImages.$invalid && newAsset.OSGImages.$dirty}" ng-if = "showUploadFile(4)">
<label>OSG Images (max 3 MB)</label>
<input type="file" multiple ngf-select="" ng-model="newAssetForm.OSGImages" name = "OSGImages" ngf-max-size="3 MB">
<p ng-repeat="image in newAssetForm.OSGImages">
{{image.name}}
</p>
<span class = "help-block has-error" ng-if="newAsset.OSGImages.$dirty">
</span>
</div>
Here is my js code:
enter code var fileReader = new FileReader();
fileReader.readAsArrayBuffer($scope.newAssetForm.OSGImages[0]);
fileReader.onload = function(e) {
console.log(e);
Upload.upload({
url: '/api/uploadAsset',
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
'projectId': $scope.projectId,
'loadValueType' : $scope.newAssetForm.loadValueType,
'outputVideoLink': $scope.newAssetForm.outputVideoLink,
'isActive': $scope.newAssetForm.isActive,
'PImageSet': PImageSet,
inputImageUrl: $scope.newAssetForm.inputImageUrl,
markerPattFile: $scope.newAssetForm.markerPattFile,
cinema: $scope.newAssetForm.cinema,
objFile: $scope.newAssetForm.objFile,
mtlFile: $scope.newAssetForm.mtlFile,
PImage: $scope.newAssetForm.PImage,
osgFile: $scope.newAssetForm.OSGFile,
osgImage: e.target.result,
},
})
.then(function onSuccess(result){
$scope.$emit('create_asset', result.data);
$modalInstance.close();
})
I tried uploading with postman and the server is getting the files.
Also, the console logs print the files correctly.
Why the client is sending empty variable?