Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money
H5 picture upload component: it can be used alone or embedded in the android native shell for interactive use with the mobile terminal. Component encapsulation based on input, complete permission issues, image upload, image compression, image to base64 format, base64 to Blob, etc
- Permissions problem: camera + storage dual permissions, camera photo, album access
- Picture upload: batch upload, upload multiple pictures at the same time
- Image compression: Use canvas compression
- Image preview: Image data is converted to Base64 format
- Duplicate image cannot be uploaded (clear input value)
Component packaging
<template>
<div @click.stop="chooseType" class="upload-wrap">
<slot name="upload">
<div class="upload-item">
<img src="/images/icon_upload.png" class="item-img" />
</div>
</slot>
<input
id="uploadIcon"
ref="uploadIcon"
@change="uploadImg($event)"
type="file"
accept="image/*"
style="display: none;"
capture="camera"
/>
</div>
</template>
<script>
export default {
name: "UploadImage".props: {
quality: {
// Image quality
type: Number.default: null,},width: {
// Image width
type: Number.default: null,},height: {
// Image height
type: Number.default: null,}},data() {
return {
picList: [],}; },methods: {}};</script>
<style lang="scss" scoped>
.upload-wrap {
.upload-item {
width: 1.68 rem;
height: 1.68 rem;
border-radius: 0.12 rem;
margin-right: 0.2 rem;
position: relative;
overflow: hidden;
.item-img {
width: 100%;
height: 100%; }}}</style>
Copy the code
Permission problems
You need to interact with clients to obtain permissions. The permission parameters on our side are those that the client has mounted on the Window
export default {
computed: {
isApp() {
return this.$store.state.nativePara.isApp; }},methods: {
// After clicking, first check permissions
chooseType() {
// The client interactively obtains permissions
if (this.getPermession()) {
// Trigger the input click event after validation
document.getElementById("uploadIcon").click(); }},getPermession() {
// If it is in app
if (this.isApp) {
// Get camera permission
const permission = window.xxx.checkPermission(
"android.permission.CAMERA"
);
if (permission === 0) {
// If not, request open
window.xxx.requestPermission("android.permission.CAMERA");
return false;
}
// Local storage permission
const permission2 = window.xxx.checkPermission(
"android.permission.WRITE_EXTERNAL_STORAGE"
);
if (permission2 === 0) {
// If not, request open
window.xxx.requestPermission(
"android.permission.WRITE_EXTERNAL_STORAGE"
);
return false; }}return true; ,}}};Copy the code
Image upload
- Check: Check whether the file is selected; Whether the file is too large; The file type is correct
- Processing: image compression, Base64 conversion
export default {
methods: {
uploadImg(e) {
// Check if any files are selected
const files = e.target.files || e.dataTransfer.files;
if(! files.length) {return;
}
// Check whether the file is too large
const file = files[0];
if (file.size / 1024 > 5000) {
this.$toast.show("The picture is too big. Please compress it and upload it again.", {
duration: 3000});return;
}
// Determine the type of file: it must be an image
if (!/^image\//.test(file.type)) {
this.$toast.show("Please upload a picture", { duration: 3000 });
// Clear the data if it is not a picture
document.getElementById("uploadIcon").value = "";
return;
}
this.convertBase64(file, (blob) = > {
const data = this.compress(blob); // Compress the photo
console.log('Compressed image size', the data length)const imageData = {
time: new Date().getTime(),
uri: data,
};
this.$emit("on-upload", imageData); }); ,}}};Copy the code
Preview picture
Image preview: Converts image data to Base64 format and returns it to the user
- Filereader. readAsDataURL(file) Gets the string of data:base64. Synchronous execution (immediate)
- Url.createobjecturl (blob) Gets an in-memory URL of the current File, representing the specified File object or BLOb object. Asynchronous execution (takes time)
export default {
methods: {
convertBase64(file, callback) {
// Check whether FileReader is supported
if (!window.FileReader) {
const URL = window.URL || window.webkitURL;
const blob = URL.createObjectURL(file); // Get the file stream of the photo
if (callback) {
callback(blob);
}
return;
}
// Create a reader
const reader = new FileReader();
// Convert the image to base64 format
reader.readAsDataURL(file);
// Callback after successful reading
reader.onloadend = (e) = > {
const result = e.target.result;
// Solve the problem of invalid upload of duplicate image: clear first
document.getElementById("uploadIcon").value = "";
// Image processing
const img = new Image();
img.src = result;
console.log("Uncompressed image", result.length);
img.onload = () = > {
if(callback) { callback(img); }}; }; ,}}};Copy the code
Image compression
export default {
methods: {
compress(img) {
// Compress proportionally by default
const width = img.width;
const height = img.height;
const scale = width / height;
/ / generated canvas
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = this.width || width;
canvas.height = this.height || width / scale || height;
/ / background
ctx.fillStyle = "#fff";
ctx.fillRect(0.0, canvas.width, canvas.height);
ctx.drawImage(img, 0.0, width, height);
// The smaller the quality value, the more blurred the image is drawn.
let quality = 0.1; // The default image quality is 0.1, with minimal compression
if (this.quality && this.quality <= 1 && this.quality > 0) {
quality = this.quality;
}
const base64 = canvas.toDataURL("image/jpeg", quality);
returnbase64; ,}}};Copy the code
Turn base64 Blob
Convert base64 image URL data to Blob
export default {
methods: {
dataURLtoBlob(dataUrl) {
const arr = dataUrl.split(",");
const mime = arr[0].match(/ : (. *?) ; /) [1];
const bStr = atob(arr[1]);
let n = bStr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bStr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime }); ,}}};Copy the code