How to preview files before uploaded to server by using file-upload component of vue.js & element-ui? - vue.js

I'm using vue.js & element-ui to upload files and preview files. I want to preview file(.pdf/.docx/.jpg...) before uploaded to server.
<el-upload
ref="uploadFile"
:on-change="onUploadChange"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:file-list="fileList"
:http-request="handleUpload"
:data="extendData"
:auto-upload="false"
class="upload-demo"
drag
action="uploadUrl"
multiple>
<i class="el-icon-upload"/>
<div class="el-upload__text">drag here, or <em>click to upload</em></div>
</el-upload>
Only the on-change function can get the content of the file, while the on-preview function only get the meta message. How to get the file content and preview that before which is uploaded to server?

It's not the meta, it's the file. So you need to use a FileReader on the file:
handlePreview(file) {
const reader = new FileReader()
reader.onload = e => console.log(e.target.result) // here is the result you can work with.
reader.readAsText(file)
}

I am also using Element-UI upload box, the following code allow user to import a JSON file to Vue, and preview its content in a new window when clicking the file name. The file is read and stored as object in data during on-change, then
Vue component:
<el-upload class="upload-box" drag action="" :auto-upload="false" :on-change="handleImport" :on-preview="handlePreview" :limit="1" :on-exceed="handleExceed">
<i class="el-icon-upload"></i>
<div class="el-upload__text">Drop file here or <em>click to upload</em></div>
<div class="el-upload__tip" slot="tip">Single JSON file with size less than 500kb</div>
</el-upload>
Script:
export default {
data() {
return {
uploadFile: null,
fileContent: null,
}
},
methods: {
handleImport(file) {
this.uploadFile = file
let reader = new FileReader()
reader.readAsText(this.uploadFile.raw)
reader.onload = async (e) => {
try {
this.fileContent = JSON.parse(e.target.result)
} catch (err) {
console.log(`Load JSON file error: ${err.message}`)
}
}
},
handlePreview() {
let myWindow = window.open();
myWindow.document.write(JSON.stringify(this.fileContent));
myWindow.document.close();
},
handleExceed(files, fileList) {
this.$message.warning(`The limit is 1, you selected ${files.length + fileList.length} totally, please first remove the unwanted file`);
},
},
}

Related

Using dropzone.js in vue, calling function with image file name

I'm having a hard time getting anything to work with this the way I need it, but I have a working dropzone instance in my Vue project.
I can upload the image and call functions within the dropzone code, however, I need to call a function directly from the form in the html in order to send the 'card' object.
All I need to do is call a function when a file is added through the dropzone form, with the filename.
My code:
<div class="uk-width-3-10">
<form v-on:change="imageChange(card)" method="post" action="{{url('product/parts/upload/store')}}" enctype="multipart/form-data"
class="dropzone" v-bind:id="'dropzone-'+i">
</form>
</div>
...
imageChange(Card){
console.log('working');
},
addCard(){
Vue.nextTick(function () {
new Dropzone("#dropzone-"+cardIndex, {
maxFilesize: 12,
renameFile: function (file) {
var dt = new Date();
var time = dt.getTime();
return time + file.name;
},
acceptedFiles: ".jpeg,.jpg,.png,.gif",
addRemoveLinks: true,
timeout: 50000,
removedfile: function (file) {
console.log(file.upload.filename);
var name = file.upload.filename;
var fileRef;
return (fileRef = file.previewElement) != null ?
fileRef.parentNode.removeChild(file.previewElement) : void 0;
},
init: function() {
this.on("addedfile",
function(file) {
instance.imageZoneNames.push({name: file.upload.filename});
console.log(file);
console.log(instance.imageZoneNames);
});
}
});
});
}
Dropzone has many events, You used removedfile() event! there is another event called addedfile() and executes when a file is added to the dropzone list
imageChange(card) {
console.log(card)
},
addCard() {
Vue.nextTick(() => {
new Dropzone('#dropzone-` + cardIndex, {
addedfile(file) {
this.imageChange(file);
}
}
}
}

How in bootstrap-vue convert FileReader to blob and upload to server?

In #vue/cli 4.1.1 app I use bootstrap-vue and b-form-file conponent for images uploading
https://bootstrap-vue.js.org/docs/components/form-file/#multiple-files
with definition :
<b-form-file
id="upload_ad_image"
v-model="new_upload_ad_image"
:state="Boolean(new_upload_ad_image)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
accept="image/jpeg, image/png, image/gif"
></b-form-file>
<div ref="uploaded_img_preview" id="uploaded_img_preview" class="m-2" >Uploaded image preview :</div>
I found snippet https://codepen.io/Tenderfeel/pen/rgqWXR
and using it I show selected file on my form for preview.
Next I need to upload it on the server. I have an expierence of uploading image as blog using code like :
fetch(this.taskRow.imageFile.blob).then(function (response) {
if (response.ok) {
return response.blob().then(function (imageBlob) {
let imageUploadData = new FormData()
imageUploadData.append('id', self.taskRow.id)
imageUploadData.append('image', imageBlob)
imageUploadData.append('image_filename', self.taskRow.imageFile.name)
But I need to convert uploading image to blob. I use method when image is selected:
But got error : Error in callback for watcher "new_upload_ad_image": "InvalidStateError: Failed to execute 'readAsDataURL' on 'FileReader': The object is already busy reading Blobs
watch: {
new_upload_ad_image(val) {
if (!val) return;
if (this.previewImg) {
this.previewImg.remove();
}
const img = document.createElement("img");
img.classList.add("obj");
img.file = this.new_upload_ad_image;
console.log('img.file::')
console.log(img.file)
this.previewImg = img;
console.log('this.$refs.uploaded_img_preview::')
console.log(this.$refs.uploaded_img_preview)
console.log('img::')
console.log(img)
this.$refs.uploaded_img_preview.appendChild(img);
const fileReader = new FileReader();
fileReader.onload = (e) => {
this.previewImg.src = e.target.result;
};
fileReader.readAsDataURL(this.new_upload_ad_image);
console.log('fileReader::')
console.log(fileReader)
let blobObj= fileReader.readAsDataURL(img.file) // RAISE ERROR :
console.log('blobObj::')
console.log(blobObj)
}
},
What I see in the console : https://imgur.com/a/2EZxq9C
How to get blob and upload it on server?
MODIFIED BLOCK :
having file input with id="upload_ad_image" defined :
<b-form-file
id="upload_ad_image"
v-model="new_upload_ad_image"
:state="Boolean(new_upload_ad_image)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
accept="image/jpeg, image/png, image/gif"
></b-form-file>
I run fetch and see that image blob is invalid and file is created, but it is invalid
I have :
var self = this
const upload_ad_image = document.getElementById('upload_ad_image')
console.log('upload_ad_image::')
console.log(upload_ad_image)
console.log('upload_ad_image.files::')
console.log(upload_ad_image.files[0])
if (typeof upload_ad_image.files[0] == 'undefined') {
self.showPopupMessage('Ad image upload', 'Invalid image !', 'warn')
return
}
fetch(upload_ad_image.files[0].blob).then(function (response) {
if (response.ok) {
return response.blob().then(function (imageBlob) {
console.log('imageBlob::')
console.log(imageBlob) // Looks like this var has invalid content(printscreen below)!
let imageUploadData = new FormData()
imageUploadData.append('ad_id', self.editableAd.id)
imageUploadData.append('main', self.new_upload_ad_image_main)
imageUploadData.append('info', self.new_upload_ad_image_info)
imageUploadData.append('image', imageBlob)
imageUploadData.append('image_filename', upload_ad_image.files[0].name)
I see in console : https://imgur.com/a/4ees55C
What is wrong and how it can be fixed ?
"bootstrap-vue": "^2.3.0",
"vue": "^2.6.11",
Thanks!
File objects do inherit from the Blob interface.
All you can do with a Blob, you can also do it with a File, so in your code you can directly append this.new_upload_ad_image to your FormData.
const inp = document.getElementById('inp');
inp.onchange = (evt) => {
const formData = new FormData();
formData.append( 'my-file', inp.files[0], 'file.ext' );
// check it's correctly in the FormData
console.log( [...formData.entries()] );
};
<input type="file" id="inp">

VueJS file upload not accepting file

I'm working on a file upload image preview with VueJS and I'm having an issue where...
1. - file get uploaded by user
2. - preview comes up beside the input field
3. - input field now says there is no image uploaded though there is the preview.
here is the html:
<input type='file' accept='image/*' #change="onChange" name='file' />
<img width='200' :src="uploadPreview" alt='preview' />
here is my vueJs code:
data: function() { return {
uploadPreview : "",
}
},
methods : {
onChange(e) {
if (! e.target.files.length) return;
let file = e.target.files[0];
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = e => {
this.uploadPreview = e.target.result; // if this line is commented out or just not present, the upload will work but the preview won't show since uploadPreview does not have a value set.
};
},
}
there's something with that line that I commented in the code there.
this.uploadPreview = e.target.result;
if this line is commented out or just not present, the upload will work but the preview won't show since uploadPreview does not have a value set.
Why is this not working? Why does the input field value for the file reset after simply setting uploadPreview to some binary image data??? Banging my head on this table once more.
I suggest you debugging points. Try and let me know.
data: function() { return {
uploadPreview : "ABCD",
}
},
methods : {
onChange(e) {
if (! e.target.files.length) return;
let file = e.target.files[0];
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = e => {
console.log("FIRST SEE WHAT'S INSIDE THE RESULTS",e.target.result);
console.log("SECOND MAKE SURE YOU CAN ACCESS",this.uploadPreview) // this should print ABCD
this.uploadPreview = e.target.result; // if this line is commented out or just not present, the upload will work but the preview won't show since uploadPreview does not have a value set.
};
},
}
and finally
<img width='200' :src="uploadPreview" :alt='uploadPreview' />
(alt should equals to image data)

Image upload for multiple fields Angular 5

I have a scenario where i have to create multiple file upload fields dynamically using reactive forms with form array and upload multiple image for that particular field in angular 5 or angular reactive forms and the image needs to be displayed parallel to that form field name .
Please help with me with any sample code in stack blitz or from any links. Also
thanks.
You can do the file upload part using formData.
const formData: FormData = new FormData();
formData.append('file1', file1, file1.name);
formData.append('file2', file2, file2);
this.http.post(url, formData);
And using the change event in the
<input type="file" (chnage)="onChange($event)"> you can get the image source of the file you select.
Here
public fileList: FileList;
public imageUrls: any[];
public files: any[];
public onChange(event) {
if (event.target.files.length === 0) {
return;
}
this.fileList = event.target.files;
for (let i = 0; i < this.fileList.length; i++) {
const file = this.fileList[i];
if (!file.type.match('image')) {
continue;
}
this.files.push(file);
const picReader = new FileReader();
picReader.onload = (e: any) => {
const picFile = e.target;
this.imageUrls.push(picFile.result);
};
picReader.readAsDataURL(file);
}
}
And in the template
<input type="file"
(change)="onChange($event)"
placeholder="Upload file"
accept="image/*" multiple>
<p>(You may choose more than one file to upload.)</p>
<ng-container *ngFor="let item of imageUrls; let i = index">
<img [src]="item" height="100" class="img-thumbnail">
</ng-container>
This is just a idea. Just give it a try.

How to get uploaded image in serverside using Ember.js

I'm new to Ember.js and I'm stuck with a problem I need to save the uploaded image in db but I dont know how to do that I wrote code for upload the image but i'm stuck with passing it to the server my current code is given below
App.js
App = Ember.Application.create();
App.PreviewImageView = Ember.View.extend({
attributeBindings: ['name', 'width', 'height', 'src'],
tagName: 'img',
viewName: 'previewImageView',
printme: function () {
console.log('in previewImageView');
}
});
App.FileField= Ember.TextField.extend({
type: 'file',
attributeBindings: ['name'],
change: function (evt) {
var input = evt.target;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
this.$().parent(':eq(0)').children('img:eq(0)').attr('src', e.target.result);
var view = that.getPath('parentView.previewImageView');
view.set('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
});
html
<script type="text/x-handlebars">
{{view App.FileField name="logo_image" contentBinding="content"}}
{{view App.PreviewImageView width="200" height="100" }}
</script>
I think you can mix some traditional MVC methods to solve your problem. from your current code I can assume that showing a preview of the image is completed so to get that file in server side just use the following code in your html
#using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" {{view Wizard.FileField contentBinding="content"}} />
<input type="submit" id="btnUpload" value="Upload" />
}
and In you controller method you can access the file like this
public ActionResult FileUpload(HttpPostedFileBase file)
{
// Do what you want
}
To save the image in db you have to convert it into bytes (sql server 2008 support image now but db like postgresql still need image as bytes) to do that use the following method
MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
byte[] bytes= target.ToArray();
return View();
Assuming you are using ember-data, you can create a model to represent the image and then create/save from the reader's onload callback. For example:
App.LogoImage = DS.Model.extend({
id: DS.attr('number'),
attachment: DS.attr('string')
});
//in App.FileField...
reader.onload = function (e) {
this.$().parent(':eq(0)').children('img:eq(0)').attr('src', e.target.result);
var view = that.getPath('parentView.previewImageView');
view.set('src', e.target.result);
var file = e.srcElement.result;
var logo = App.LogoImage.createRecord({ attachment: file });
logo.save();
}