注意:重点关注这几个js方法:
1、递归压缩文件: doCompressImage()
2、具体的图片文件压缩方法:compressImage()
3、将Blob 转换为 base64: blobToBase64()
以下代码,可以直接拷进html文件中,在浏览器打开即可看到效果。(以下代码是h5)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片压缩上传</title>
<link rel="stylesheet" href="https://www.layuicdn.com/layui-v2.5.6/css/layui.css">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://www.layuicdn.com/layui-v2.5.6/layui.js"></script>
</head>
<style>
.info-div {
width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;
}
.title {
width: 100%;
font-size: 15px;
background: linear-gradient(94deg,#69a7ea, #3c81d5 100%);
color: #FFFFFF;
height: 36px;
line-height: 36px;
font-family: PingFang SC, PingFang SC-Medium;
margin-top: 15px;
}
.details_title {
padding-left:10px
}
.btn.btn-raised.btn-inverse, .input-group-btn .btn.btn-raised.btn-inverse, .btn.btn-fab.btn-inverse, .input-group-btn .btn.btn-fab.btn-inverse, .btn-group-raised .btn.btn-inverse, .btn-group-raised .input-group-btn .btn.btn-inverse {
background-color: #3f51b5;
color: #ffffff;
}
.file-dev {
width: 100%;
padding-left: 15px;
}
.file-dev-row{
display:flex;flex-direction: row;align-items: center;margin-top:20px;padding: 0px 20px 0px 10px
}
.file-dev-row-title {
display:flex;flex-direction: row;flex: 1;align-items: center;
}
.uploading-catalog-btn {
width: 54px;
height: 25px;
background: #009688;
border: 1px solid #dcdfe6;
border-radius: 3px;
font-size: 12px;
font-family: Microsoft YaHei;
color: #ffffff;
cursor: pointer;
}
.list-group-item {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
padding-left: 15px;
color: #5a95c1;
padding-right: 15px;
width: 90vw
}
.file-name {
width: 100% !important;
float: left !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: normal !important;
}
</style>
<body>
<div class="info-div">
<div class="title">
<p class="details_title">申请材料</p>
</div>
<div class="file-dev">
<div class="file-dev-row">
<div class="file-dev-row-title" >
<!-- <img src="/resource/default/static/mobile/image/icon/catalogue-icon.png" alt=""> -->
<p>申请人图像<span style="color:red">(必选)</span></p>
</div>
<button type="button" class="uploading-catalog-btn" onclick="document.getElementById('file1').click();">上传</button>
<input type="file" style="display: none;" id="file1" class="btn btn-raised btn-inverse" name="申请人图像" onchange="changeImg(this,'file1')">
</div>
<ul class="list-group" id="申请人图像ul"></ul>
</div>
</div>
</body>
<script>
let UploadMatList = [];//上传材料列表
var imgSubmitData = {
ApplyFileList: [],
MatType: ""
}
//图片上传到服务器所需要的参数
var imgData = {
MATERIALNAME: "",
PATH: "",
EXT: ""
}
//选择图片事件
function changeImg(imgObj,domeId) {
var matTypeName = imgObj.name;
var files = imgObj.files;
var img = files[0];
if (img == null) {
return;
}
//取图片名字与后缀名
var imgName = img.name;
var index = imgName.lastIndexOf('.');
var strtype = imgName.substr(index + 1, imgName.length - index);
strtype = strtype.toLowerCase();
if (!(strtype == "png" || strtype == "jpg" || strtype == "gif" || strtype == "jpeg")) {
layui.use(['layer'], function () {
var layer = layui.layer
layer.alert('请上传gif,jpg,png,jpeg格式的图片!');
})
$(imgObj).val("");
} else {
imgName = imgName.substring(0, index);
if (img) {
var reader = new FileReader();
reader.readAsDataURL(img);
reader.onload = function () {
var CONTENT;
var base64 = reader.result;
//图片大小 < 600kb 直接上传到服务器 如需要调整,可直接修改下面的判断
if(img.size <= 1024*600){
if (strtype == "jpg") {
CONTENT = base64.replace("data:image/jpeg;base64,", "");
} else if (strtype == "png") {
CONTENT = base64.replace("data:image/png;base64,", "");
} else if (strtype == "gif") {
CONTENT = base64.replace("data:image/gif;base64,", "");
}else if (strtype == "jpeg") {
CONTENT = base64.replace("data:image/jpeg;base64,", "");
}
//调用接口上传文件
SendRequestUploadFile(CONTENT,strtype,imgName,matTypeName,domeId);
}else {
// quality 图片质量值 wh 初始化需要缩小的宽度和高度
var quality = 0.8,wh = 50;
//多是M,只取整数部分
var num = parseInt(img.size/(1024*1024))
//quality 和 wh 重置初始值,会使下面的递归压缩次数变少,效率高一些
quality = 1-0.1*num
wh = num*wh
layui.use(['element', 'layer','form'], function () {
var layer = layui.layer;
var load = layer.msg("请求中...", { icon: 16,time: false, shade: 0.01});
try {
//压缩文件
doCompressImage(img,img.width,img.height,strtype,quality,wh,imgName,matTypeName,img.type,load,domeId)
}catch (e){
if(e.message == '上传文件失败'){
layer.alert("上传文件失败!");
}else {
layer.alert(e.message);
}
layer.close(load);
}finally {
$("#"+domeId).val("")
}
})
}
};
}
}
}
//递归压缩文件
function doCompressImage(file, maxWidth, maxHeight,fileType,quality,wh,imgName,matTypeName,type,load,domeId) {
compressImage(file,maxWidth,maxHeight,fileType,quality,wh).then((blob)=>{
if(blob.size > 1024*600){
if(quality > 0.2){
quality = quality - 0.1
}
const file = new File([blob], imgName, { type: type, lastModified: Date.now() });
doCompressImage(file,maxWidth, maxHeight,fileType,quality,wh+10,imgName,matTypeName,type,load,domeId)
}else {
blobToBase64(blob).then((base)=>{
var CONTENT;
if (fileType == "jpg") {
CONTENT = base.replace("data:image/jpeg;base64,", "");
} else if (fileType == "png") {
CONTENT = base.replace("data:image/png;base64,", "");
} else if (fileType == "gif") {
CONTENT = base.replace("data:image/gif;base64,", "");
}else if (fileType == "jpeg") {
CONTENT = base.replace("data:image/jpeg;base64,", "");
}
console.log("压缩成功!")
layer.close(load);
//上传文件
SendRequestUploadFile(CONTENT,fileType,imgName,matTypeName,load,domeId,domeId);
})
}
})
}
//图片文件压缩
function compressImage(file, maxWidth, maxHeight,fileType,quality,wh) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
let width = img.width-wh;
let height = img.height-wh;
if (width > maxWidth) {
height *= maxWidth / width;
width = maxWidth;
}
if (height > maxHeight) {
width *= maxHeight / height;
height = maxHeight;
}
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(
blob => {
resolve(blob)
},
file.type,
quality // 压缩质量,可以根据需要调整
);
};
img.onerror = reject;
img.src = URL.createObjectURL(file);
});
}
// 将Blob 转换为 base64
function blobToBase64 (blob) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader()
fileReader.onload = (e) => {
resolve(e.target.result)
}
// readAsDataURL
fileReader.readAsDataURL(blob)
fileReader.onerror = () => {
reject(new Error('blobToBase64 error'))
}
})
}
//文件上传,根据自己项目中的方法来修改,这里只做参考
function SendRequestUploadFile(base64Str,ext,imgName,matTypeName,load,domeId) {
var imgSubmitDataCopy = JSON.parse(JSON.stringify(imgSubmitData));
var imgDataCopy = JSON.parse(JSON.stringify(imgData));
imgSubmitDataCopy.MatType = matTypeName;
imgDataCopy.MATERIALNAME = imgName;
imgDataCopy.EXT = ext;
//上传文件接口参数
var uploadFileBody = {
base64Str: base64Str,
ext: ext,
}
//上传文件接口地址
var sendUrl = '';
//具体上传方法,根据自己项目来
/**
httpUtil.post(sendUrl,paramStr).then(res=>{
layer.close(load);
if(true){
imgDataCopy.PATH = res.data
imgSubmitDataCopy.ApplyFileList.push(imgDataCopy);
var falg = false;
for (let i = 0; i < UploadMatList.length; i++) {
if( UploadMatList[i].MatType == matTypeName){
UploadMatList[i].ApplyFileList.push(imgDataCopy)
falg = true
}
}
if(!falg){
UploadMatList.push(imgSubmitDataCopy)
}
AddMat(imgSubmitDataCopy, imgDataCopy)
}
})
**/
//以下代码仅做参考,效果展示,真是项目中,应该在文件上传成功后执行下面代码
imgDataCopy.PATH = ""
imgSubmitDataCopy.ApplyFileList.push(imgDataCopy);
var falg = false;
for (let i = 0; i < UploadMatList.length; i++) {
if( UploadMatList[i].MatType == matTypeName){
UploadMatList[i].ApplyFileList.push(imgDataCopy)
falg = true
}
}
if(!falg){
UploadMatList.push(imgSubmitDataCopy)
}
AddMat(imgSubmitDataCopy, imgDataCopy)
/**
**/
}
//添加材料
function AddMat(imgItem, imgData) {
//如果第一次添加,则添加
//不是第一次,则直接往相应的数据类型材料数组里面push
for (var i = 0; i < UploadMatList.length; i++) {
if (UploadMatList[i].MatType == imgItem.MatType) {
//记录在数组中的索引,以便删除
var imgArrIndex = UploadMatList[i].ApplyFileList.length - 1;
var content = '<li class="list-group-item" indexID="' + imgArrIndex + '">' + '<span class="file-name">'+imgData.MATERIALNAME + imgData.EXT+'</span>'+'<span style="margin-right: 15px;color: #25a251" onclick="lookTupian(\''+imgData.PATH +'\')">查看</span> ' +'<span style="color: red" onclick="deltr(\''+imgItem.MatType+'\','+imgArrIndex+')">删除</span> '+ '</li>'
AddMatLi(imgItem.MatType + "ul", content);
return;
}
}
}
//上传材料的时候添加多个材料
function AddMatLi(toObjStr, content) {
$("#" + toObjStr).append(content);
}
var deltr = function(matType,index){
if(UploadMatList.length > 0){
for (let i = 0; i < UploadMatList.length; i++) {
if( UploadMatList[i].MatType == matType){
if(UploadMatList[i].ApplyFileList.length >= index+1){
UploadMatList[i].ApplyFileList.splice(index,1)
RemoveMatLi(matType,UploadMatList[i].ApplyFileList)
break
}
}
}
}
}
//移除文件
function RemoveMatLi(matType,arr) {
$("#" + matType + "ul").html("");
for (let i = 0; i < arr.length; i++) {
// var content = '<li class="list-group-item" indexID="' + i + '">' + arr[i].MATERIALNAME + arr[i].EXT +'<span style="color: red" onclick="deltr(\''+matType+'\','+i+')">删除</span> '+ '</li>'
var content = '<li class="list-group-item" indexID="' + i + '">' + '<span class="file-name">'+arr[i].MATERIALNAME + arr[i].EXT +'</span>'+'<span style="margin-right: 15px;color: #25a251" onclick="lookTupian(\''+arr[i].PATH +'\')">查看</span> '+'<span style="color: red" onclick="deltr(\''+matType+'\','+i+')">删除</span> '+ '</li>'
AddMatLi(matType + "ul", content);
}
}
//初始化上传文件dom
function createUploadFileDom(fileDate) {
if(fileDate && fileDate.length > 0){
fileDate.forEach((item, index) => {
if(item.ApplyFileList && item.ApplyFileList.length > 0){
item.ApplyFileList.forEach((itemfile, index) => {
AddMat(item, itemfile)
})
}
})
}
}
</script>
</html>