tips:如果本文對你有用,請愛心點個贊,提高排名,讓這篇文章幫助更多的人。謝謝大家!比心❤~ 如果解決不了,可以在文末加我微信,進群交流。 技術選型 開發框架: uniapp 主題UI框架: uView 背景 uView框架upload文件上傳組件中沒有h5端控制壓縮的參數,超出文件大小也沒有響應 ...
tips:如果本文對你有用,請愛心點個贊,提高排名,讓這篇文章幫助更多的人。謝謝大家!比心❤~
如果解決不了,可以在文末加我微信,進群交流。
技術選型
背景
uView框架upload文件上傳組件中沒有h5端控制壓縮的參數,超出文件大小也沒有響應的提示,但是一般的上傳文件場景,是需要控制文件大小的。
效果圖
原圖是4.8M,長寬為:3024*4032
封裝圖片壓縮工具方法
- 封裝util.js
// 圖片壓縮
/**
* imgSrc 地址
* scale 壓縮質量 0-1
* type 文件類型
*/
export function compressImg(imgSrc, scale, type, callback) {
// uni.$u.toast('壓縮中')
var img = new Image();
img.src = imgSrc;
img.onload = function() {
var that = this;
var h = (img.height * scale).toFixed(0); // 預設按質量比例壓縮
var w = (img.width * scale).toFixed(0);
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var width = document.createAttribute("width");
width.nodeValue = w;
var height = document.createAttribute("height");
height.nodeValue = h;
canvas.setAttributeNode(width);
canvas.setAttributeNode(height);
ctx.drawImage(that, 0, 0, w, h);
var base64 = canvas.toDataURL('image/jpeg', scale); //壓縮比例
canvas = null;
if (type == 'base64') {
let data = {
size: getBase64Size(base64),
type: type,
source: base64
}
callback(base64);
} else {
let blob = base64ToBlob(base64);
// console.log('壓縮後的大小', blob, blob.size, blob.type)
const blobUrl = window.URL.createObjectURL(blob); //blob地址
blob.source = blobUrl
callback(blob);
}
}
}
// base轉Blob
export function base64ToBlob(base64) {
var arr = base64.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
// 獲取base64的文件大小
export function getBase64Size(base64Str) {
let size = 0;
if (base64Str) { // 獲取base64圖片byte大小
const equalIndex = base64Str.indexOf('='); // 獲取=號下標
if (equalIndex > 0) {
const str = base64Str.substring(0, equalIndex); // 去除=號
const strLength = str.length;
const fileLength = strLength - (strLength / 8) * 2; // 真實的圖片byte大小
size = Math.floor(fileLength); // 向下取整
} else {
const strLength = base64Str.length;
const fileLength = strLength - (strLength / 8) * 2;
size = Math.floor(fileLength); // 向下取整
}
} else {
size = null;
}
return size
}
index.vue中引入util.js,併在上傳時使用
<template>
<view class="components-wrap">
<u-form-item class='form-item-box' labelWidth='auto' :prop="column.name" borderBottom :ref="column.name">
<u-upload class="upload-wrap" width="102" :fileList="fileList" @afterRead="afterRead" @delete="deletePic"
:sizeType="sizeType" @clickPreview="clickPreview" :name="column.name" multiple :disabled="disabled"
:formkey="formkey">
<view class="material-add">
<u-button class='upload-btn' :disabled="disabled" text="上傳圖片"></u-button>
</view>
</u-upload>
</u-form-item>
</view>
</template>
<script>
import {
compressImg
} from '@/utils/util.js'
export default {
data() {
return {
currentValue: false,
fileList: [],
sizeType: ['compressed'],
fileMaxSize: 2 * 1024 * 1024, // 預設最大為2M
fileMinSize: 50 * 1024 // 最小為50KB
}
},
methods: {
clickPreview(url, lists, name) {
console.log('預覽圖片', url, lists, name)
},
getCompressionRatio(fileSize) {
const multiple = (fileSize / this.fileMaxSize).toFixed(2) // 獲取文件大小倍數,生成質量比
let compressionRatio = 1
if(multiple > 5) {
compressionRatio = 0.5
} else if (multiple > 4) {
compressionRatio = 0.6
} else if (multiple > 3) {
compressionRatio = 0.7
}else if (multiple > 2) {
compressionRatio = 0.8
} else if (multiple > 1) {
compressionRatio = 0.9
} else {
compressionRatio = 2
}
return compressionRatio;
},
// 新增圖片
async afterRead(event) {
// 當設置 mutiple 為 true 時, file 為數組格式,否則為對象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList`].length
for (let index in lists) {
const item = lists[index]
const fileSize = item.size
const fileName = item.name ?? ''
if (fileSize > this.fileMaxSize) {
const compressionRatio = this.getCompressionRatio(fileSize)
if (compressionRatio > 1) {
uni.$u.toast('文件' + fileName + '大於10M')
return false
}
// 自動壓縮圖片'
await this.compressImg(item, compressionRatio)
if (item.size > this.fileMaxSize) {
uni.$u.toast('文件' + fileName + '壓縮後超出2M')
return false
}
}
if (item.size < this.fileMinSize) {
uni.$u.toast('文件' + fileName + '不能小於50KB')
return false
}
this[`fileList`].push({
...item,
status: 'uploading',
message: '上傳中'
})
}
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
// 垃圾回收
window.URL.revokeObjectURL(lists[i].url)
console.log('上傳結果', result)
let item = this[`fileList`][fileListLen]
this[`fileList`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '上傳成功',
url: result
}))
fileListLen++
}
},
compressImg(source, compressionRatio) {
return new Promise((resolve, reject) => {
compressImg(source.url, compressionRatio, source.type, compressRes => {
resolve(compressRes);
})
}).then((res) => {
source.size = res.size
// window.URL.revokeObjectURL(source.url) // 刪除被壓縮的緩存文件,這裡註意,如果是相冊選擇上傳,可能會刪除相冊的圖片
source.url = res.source
source.thumb = res.source
return source
}).catch(err => {
console.log('圖片壓縮失敗', err)
})
},
uploadFilePromise(url) {
let that = this
return new Promise((resolve, reject) => {
const uploadTask = uni.uploadFile({
url: uploadUrl,
filePath: url,
name: 'file',
header: {
"blade-auth": "Bearer xxxxxxxxxxxxx",
"tenantCode": tenantCode
},
success: (uploadFileRes) => {
if (uploadFileRes.statusCode === that.Response.OK) {
const data = JSON.parse(uploadFileRes.data)
if (data.code === that.Response.OK) {
console.log('form components upload uploadFilePromise onchange',
uploadFileRes)
let fileId = data.data[0].id;
const sourceUrl = 'https://xxxxxxx/download-document/id/' + fileId;
that.data.value.push({
id: fileId,
name: data.data[0].name,
source: sourceUrl
});
// 添加圖片數量
that.data.count = that.fileList.length
that.$emit('change', that.data, that.formkey)
setTimeout(() => {
resolve(sourceUrl)
}, 500)
} else {
uni.showToast({
title: data.msg,
icon: 'none',
duration: that.ShowToast.DURATION
});
}
} else {
console.log(uploadFileRes)
uni.showToast({
title: '上傳失敗',
icon: 'none',
duration: that.ShowToast.DURATION
});
}
},
fail(error) {
// reject(false)
uni.$u.toast(error.errMsg)
console.log('圖片上傳失敗', error)
}
});
// uploadTask.onProgressUpdate((res) => {
// console.log('上傳進度' + res.progress);
// console.log('已經上傳的數據長度' + res.totalBytesSent);
// console.log('預期需要上傳的數據總長度' + res.totalBytesExpectedToSend);
// // 測試條件,取消上傳任務。
// if (res.progress > 50) {
// uploadTask.abort();
// }
// });
})
},
}
}
<script/>
如果本文對你有幫助,請有問題請添加個人微信:【mengyilingjian】,進群一起技術討論。添加時請備註來意,謝謝!