Last active
April 29, 2021 19:32
-
-
Save manuelgeek/f8473555d17017b4c3fb9a7f1e2b366f to your computer and use it in GitHub Desktop.
FileUpload.vue and FileUploadCompress.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="tw-flex tw-content-between tw-flex-wrap"> | |
<v-card class="tw-rounded-lg c-bg-gray tw-flex tw-justify-center tw-flex-wrap" :flat="true"> | |
<div class="image-preview tw-px-8 md:tw-px-12 tw-py-2" v-if="imageData.length > 0"> | |
<div v-if="allowDelete" class="tw-w-full tw-flex tw-justify-end tw-absolute tw--ml-20 tw--mt-3"> | |
<v-icon class="tw-bg-red-700 tw-rounded-full tw-p-1 tw-cursor-pointer" title="remove image" size="17" color="#fff" @click="deleteImage">mdi-close</v-icon> | |
</div> | |
<img class="preview" :src="imageData" alt="img" /> | |
</div> | |
<label v-else class="tw-flex tw-items-center tw-px-8 md:tw-px-12 tw-py-4 md:tw-py-8 tw-cursor-pointer"> | |
<v-icon class="c-bg-blue tw-rounded-full tw-w-6 tw-h-6" color="#fff">mdi-plus</v-icon> | |
<p class="c-blue-text tw-mt-3 tw-px-3">Attach Image</p> | |
<input type="file" :id="name" class="tw-hidden" @change="previewImage" accept="image/*" /> | |
<v-text-field class="tw-hidden" v-model="image" :rules="rules"></v-text-field> | |
</label> | |
</v-card> | |
<small class="tw-w-full tw-p-2">maximum of 2 MB</small> | |
</div> | |
</template> | |
<script> | |
import helpers from '@/utils/helpers'; | |
export default { | |
name: 'FileUploads', | |
props: { | |
rules: { | |
type: Array, | |
required: false, | |
}, | |
name: String, | |
addedImage: { | |
type: Object, | |
required: false, | |
}, | |
}, | |
data() { | |
return { | |
imageData: '', | |
image: '', | |
allowDelete: true, | |
}; | |
}, | |
watch: { | |
image(val) { | |
this.$emit('input', val); | |
}, | |
}, | |
mounted() { | |
// console.log('here1', this.addedImage); | |
if (!helpers.objIsEmpty(this.addedImage)) { | |
this.image = this.addedImage; | |
this.imageData = atob(this.addedImage.base64String); | |
} | |
}, | |
methods: { | |
previewImage(event) { | |
const input = event.target; | |
if (input.files && input.files[0]) { | |
if (/\.(jpe?g|png|gif)$/i.test(input.files[0].name)) { | |
const FileSize = input.files[0].size / 1024 / 1024; | |
if (FileSize > 2) { | |
this.$toast.error('Image greater than 2 MB', 'Image Error'); | |
return; | |
} | |
const reader = new FileReader(); | |
reader.onload = (e) => { | |
this.imageData = e.target.result; | |
this.image = { | |
base64String: btoa(e.target.result), | |
documentId: -1, | |
documentName: this.name, | |
}; | |
}; | |
reader.readAsDataURL(input.files[0]); | |
} else { | |
this.$toast.error('Not Valid Image', 'Image Error'); | |
} | |
} | |
}, | |
deleteImage() { | |
this.imageData = ''; | |
this.image = ''; | |
}, | |
}, | |
}; | |
</script> | |
<style scoped> | |
img.preview { | |
width: 200px; | |
background-color: white; | |
border: 1px solid #DDD; | |
padding: 5px; | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="tw-flex tw-content-between tw-flex-wrap"> | |
<v-card class="tw-rounded-lg c-bg-gray tw-flex tw-justify-center tw-flex-wrap" :flat="true"> | |
<div class="image-preview tw-px-8 md:tw-px-12 tw-py-2" v-if="imageData.length > 0"> | |
<div v-if="allowDelete" class="tw-w-full tw-flex tw-justify-end tw-absolute tw--ml-20 tw--mt-3"> | |
<v-icon class="tw-bg-red-700 tw-rounded-full tw-p-1 tw-cursor-pointer" title="remove image" size="17" color="#fff" @click="deleteImage">mdi-close</v-icon> | |
</div> | |
<img class="preview" :src="imageData" alt="img" /> | |
</div> | |
<label v-else class="tw-flex tw-items-center tw-px-8 md:tw-px-12 tw-py-4 md:tw-py-8 tw-cursor-pointer"> | |
<v-icon class="c-bg-blue tw-rounded-full tw-w-6 tw-h-6" color="#fff">mdi-plus</v-icon> | |
<p class="c-blue-text tw-mt-3 tw-px-3">Attach Image</p> | |
<input type="file" :id="name" class="tw-hidden" @change="previewImage" accept="image/*" /> | |
<v-text-field class="tw-hidden" v-model="image" :rules="rules"></v-text-field> | |
</label> | |
</v-card> | |
<small class="tw-w-full tw-p-2">maximum of 2 MB</small> | |
</div> | |
</template> | |
<script> | |
import helpers from '@/utils/helpers'; | |
export default { | |
name: 'FileUploads', | |
props: { | |
rules: { | |
type: Array, | |
required: false, | |
}, | |
name: String, | |
addedImage: { | |
type: Object, | |
required: false, | |
}, | |
}, | |
data() { | |
return { | |
imageData: '', | |
image: '', | |
allowDelete: true, | |
file: {}, | |
result: {}, | |
reader: {}, | |
scale: 100, | |
quality: 20, | |
}; | |
}, | |
watch: { | |
image(val) { | |
this.$emit('input', val); | |
}, | |
}, | |
mounted() { | |
// console.log('here1', this.addedImage); | |
if (!helpers.objIsEmpty(this.addedImage)) { | |
this.image = this.addedImage; | |
this.imageData = atob(this.addedImage.base64String); | |
} | |
}, | |
methods: { | |
previewImage(event) { | |
const input = event.target; | |
// get the file | |
// eslint-disable-next-line prefer-destructuring | |
this.file = input.files[0]; | |
// console.log(this.file); | |
if (input.files && this.file) { | |
if (/\.(jpe?g|png|gif)$/i.test(this.file.name)) { | |
const FileSize = this.file.size / 1024 / 1024; | |
if (FileSize > 5) { | |
this.$toast.error('Image greater than 2 MB', 'Image Error'); | |
return; | |
} | |
// Make new FileReader | |
this.reader = new FileReader(); | |
// Convert the file to base64 text | |
this.reader.readAsDataURL(this.file); | |
// on reader load something... | |
this.reader.onload = this.fileOnLoad; | |
} else { | |
this.$toast.error('Not Valid Image', 'Image Error'); | |
} | |
} | |
}, | |
/* | |
Draw And Compress The Image | |
@params {String} imgUrl | |
*/ | |
drawImage(imgUrl, type) { | |
// Recreate Canvas Element | |
const canvas = document.createElement('canvas'); | |
// Set Canvas Context | |
const ctx = canvas.getContext('2d'); | |
// Create New Image | |
const img = new Image(); | |
img.src = imgUrl; | |
img.onload = () => { | |
// Image Size After Scaling | |
const scale = this.scale / 100; | |
const width = img.width * scale; | |
const height = img.height * scale; | |
// Set Canvas Height And Width According to Image Size And Scale | |
canvas.setAttribute('width', width); | |
canvas.setAttribute('height', height); | |
ctx.drawImage(img, 0, 0, width, height); | |
// Quality Of Image | |
const quality = this.quality ? (this.quality / 100) : 1; | |
// If all files have been proceed | |
const base64 = canvas.toDataURL(type, quality); | |
const fileName = this.result.file.name; | |
const objToPass = { | |
canvas, | |
original: this.result, | |
compressed: { | |
base64, | |
name: fileName, | |
file: this.buildFile(base64, fileName), | |
}, | |
}; | |
objToPass.compressed.size = `${Math.round(objToPass.compressed.file.size / 1000)} kB`; | |
objToPass.compressed.type = type; | |
this.imageData = objToPass.compressed.base64; | |
this.image = { | |
base64String: btoa(this.imageData), | |
documentId: -1, | |
documentName: this.name, | |
}; | |
console.log(objToPass); | |
}; | |
}, | |
/* | |
When The File in loaded | |
*/ | |
fileOnLoad() { | |
// The File | |
const { file } = this; | |
// Make a fileInfo Object | |
const fileInfo = { | |
name: file.name, | |
type: file.type, | |
size: `${Math.round(file.size / 1000)} kB`, | |
base64: this.reader.result, | |
file, | |
}; | |
// Push it to the state | |
this.result = fileInfo; | |
// DrawImage | |
this.drawImage(this.result.base64, file.type); | |
}, | |
// Convert Blob To File | |
buildFile(blob, name) { | |
return new File([blob], name); | |
}, | |
deleteImage() { | |
this.imageData = ''; | |
this.image = ''; | |
this.file = {}; | |
this.result = {}; | |
this.reader = {}; | |
}, | |
}, | |
}; | |
</script> | |
<style scoped> | |
img.preview { | |
width: 200px; | |
background-color: white; | |
border: 1px solid #DDD; | |
padding: 5px; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment