使用js在layui中实现上传图片压缩


Posted in Javascript onJune 18, 2019

一、关于js上传图片压缩的方法,百度有很多种方法,这里我参考修改了一下

function photoCompress(file, w, objDiv) {
var ready = new FileReader();
/*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
ready.readAsDataURL(file);
ready.onload = function() {
var re = this.result;
canvasDataURL(re, w, objDiv);
}
};
function canvasDataURL(path, obj, callback) {
var img = new Image();
img.src = path;
img.onload = function() {
var that = this;
// 默认按比例压缩
var w = that.width,
h = that.height,
scale = w / h;
w = obj.width || w;
h = obj.height || (w / scale);
var quality = 0.5; // 默认图片质量为0.7
//生成canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 创建属性节点
var anw = document.createAttribute("width");
anw.nodeValue = w;
var anh = document.createAttribute("height");
anh.nodeValue = h;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(that, 0, 0, w, h);
// 图像质量
if(obj.quality && obj.quality <= 1 && obj.quality > 0) {
quality = obj.quality;
}
// quality值越小,所绘制出的图像越模糊
var base64 = canvas.toDataURL('image/jpeg', quality);
// 回调函数返回base64的值
callback(base64);
}
}
function convertBase64UrlToBlob(urlData) {
var arr = urlData.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
});
}

以上是压缩图片的方法,核心是将图片放入canvas内,再用canvas.toDataURL方法进行压缩,最后生成一个Blob对象。

注:因为牵扯到canvas,所以低版本浏览器应该是不支持的吧(有待考证)

二、图片压缩的方法有了,怎么使用呢?怎么上传到后台呢?往下看!

html部分:

<form action="file/uploadDoc" enctype="multipart/form-data" method="post" id="form">
<input type="file" id="file" name="file" />
<input type="submit" value="上传" />
</form>

js部分:

$("#file").change(function() {
var formData = new formData("form");
var file = this.files[0];
photoCompress(file, {
quality: 0.5,
}, function(base64Codes) {
var bl = convertBase64UrlToBlob(base64Codes);
formData.set("file", bl, file.name);
});
});

当选择文件以后,使用photoCompress方法对上传的图片进行压缩,photoCompress方法的第二个参数还可以传入长宽等参数,具体可以看photoCompress这个方法,quality是用来设置压缩后图片质量的,越小质量越差,表现出来就是图片越模糊,但是相应的体积就越小。

最后使用formData.set(key,value,name)方法,将现有的name为file的表单元素的值改变。这个方法有三个参数,第一个是key值,也就是表单里对应的元素的name值(如果不存在会自行添加),第二个值是value值,第三个是选填的值,如果第二个值为blob对象或者file对象,则第三个值表示文件名。

当然,如果你不想用form表单提交,你也可以用ajax提交的方法:

html:

 

<form enctype="multipart/form-data" method="post" id="form">
<input type="file" id="file" name="file" />
<input type="button" value="上传" id="uploadBtn"/>
</form>

有些许的变化,form没有了action,上传的按钮type改为了button

js部分给按钮添加一个点击事件,其他也没有变化,不做过多赘述:

$("#uploadBtn").click(function () {
var formData = new formData("form");
$.ajax({
type:"post",
url:"",
async:true,
data:formData,
success:function (data) {
},
error:function (e) {
}
});
});

三、结合layui踩的一些坑,以及最终的解决方法。

先看html部分:

<button type="button" class="layui-btn" id="upImg">上传图片</button>
<div id="img_list">
</div>
<input type="button" id = "btnHide" class="none">

就是这么简单。为什么要再写一个隐藏的按钮,之后解释。

js部分:

layui.use('upload', function() {
var upload = layui.upload;
var uploadInst = upload.render({
elem: '#upImg',
url: '/upload/',
auto: false,
bindAction: "#btnHide",
choose: function(obj) {
var files = obj.pushFile();
var index, file, indexArr = [];
for(index in files) {
indexArr.push(index);
};
var iaLen = indexArr.length;
file = files[indexArr[iaLen - 1]];
for(var i = 0; i < iaLen - 1; i++) {
delete files[indexArr[i]];
}
try {
if(file.size > 200 * 1024) {
delete files[index];
photoCompress(file, {
quality: 0.5,
}, function(base64Codes) {
var bl = convertBase64UrlToBlob(base64Codes);
obj.resetFile(index, bl, file.name);
$("#btnHide").trigger("click");
});
} else {
$("#btnHide").trigger("click");
}
} catch(e) {
$("#btnHide").trigger("click");
}
},
done: function(res) {
//这里把后台返回的数据进行操作,展示上传完成的图片,具体数据格式参考layui的API
},
error: function() {
}
});
});

原理:在选择照片之后,获取文件,转换为blob对象,使用resetFile方法对文件列队里的文件进行重新设置,然后再触发上传事件。

踩的坑:

1、resetFile这个方法是layui 2.3.0 新增的,所以首先要确保layui的版本是最新的。

2、我把auto设置为false,点击btnHide时触发上传,我也试过自动上传,自动上传的话,这些操作的代码就要写在before方法中(具体看layui的API),然而我发现自动上传修改文件列队的方法总是在上传成功之后才调用,这就导致实际上传的图片其实没有压缩,至于为什么是这个执行顺序我隐约觉得是不是图片转码,放入canvas的时候耽误了……具体原因我不明白,所以我用手动上传,确认修改了文件列队,再手动触发上传。

3、关于文件列队,多次上传文件,文件列队也就是obj.pushFile()返回的是多个文件的对象,而且这些文件对象的key还是一串随机数……所以我的思路是上传一次,就用delete方法删除队列中已上传过的文件。至于为什么不直接全部清空,因为考虑到不需要压缩的情况,如果全部清空,不压缩,就没有执行resetFile方法,文件列队里就没有文件,会报错。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery写一个鼠标拖动效果实现原理与代码
Dec 24 Javascript
js自定义事件及事件交互原理概述(一)
Feb 01 Javascript
javascript实现table表格隔行变色的方法
May 13 Javascript
javascript实现日期时间动态显示示例代码
Sep 08 Javascript
JS实现淡蓝色简洁竖向Tab点击切换效果
Oct 06 Javascript
JavaScript对象数组如何按指定属性和排序方向进行排序
Jun 15 Javascript
jquery ui sortable拖拽后保存位置
Apr 27 jQuery
layui表格checkbox选择全选样式及功能的实例
Mar 07 Javascript
Vue实现一个图片懒加载插件
Mar 11 Javascript
微信小程序实现下拉刷新动画
Jun 21 Javascript
Jquery动态列功能完整实例
Aug 30 jQuery
vue路由切换时取消之前的所有请求操作
Sep 01 Javascript
jquery中为什么能用$操作
Jun 18 #jQuery
详解Vue3.0 前的 TypeScript 最佳入门实践
Jun 18 #Javascript
利用js-cookie实现前端设置缓存数据定时失效
Jun 18 #Javascript
vue中利用Promise封装jsonp并调取数据
Jun 18 #Javascript
实用Javascript调试技巧分享(小结)
Jun 18 #Javascript
Angular中innerHTML标签的样式不起作用的原因解析
Jun 18 #Javascript
小程序click-scroll组件设计
Jun 18 #Javascript
You might like
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
php设计模式之简单工厂模式详解
2014/09/04 PHP
详解 PHP加密解密字符串函数附源码下载
2015/12/18 PHP
php实现文章置顶功能的方法
2016/10/20 PHP
JQuery 图片延迟加载并等比缩放插件
2009/11/09 Javascript
JavaScript Object的extend是一个常用的功能
2009/12/02 Javascript
jquery 1.4.2发布!主要是性能与API
2010/02/25 Javascript
jquery json 实例代码
2010/12/02 Javascript
PHP守护进程实例
2015/03/06 Javascript
jquery实现鼠标滑过小图查看大图的方法
2015/07/20 Javascript
Jquery技巧(必须掌握)
2016/03/16 Javascript
JQuery的Pager分页器实现代码
2016/05/03 Javascript
JS关闭窗口时产生的事件及用法示例
2016/08/20 Javascript
原生js实现电商侧边导航效果
2017/01/19 Javascript
使用JavaScript实现表格编辑器(实例讲解)
2017/08/02 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
2017/12/13 Javascript
JavaScript的变量声明与声明提前用法实例分析
2019/11/26 Javascript
解决antd datepicker 获取时间默认少8个小时的问题
2020/10/29 Javascript
Vue向后台传数组数据,springboot接收vue传的数组数据实例
2020/11/12 Javascript
[51:53]完美世界DOTA2联赛决赛日 Inki vs LBZS 第二场 11.08
2020/11/10 DOTA
在win和Linux系统中python命令行运行的不同
2016/07/03 Python
基于python脚本实现软件的注册功能(机器码+注册码机制)
2016/10/09 Python
Python实现爬虫抓取与读写、追加到excel文件操作示例
2018/06/27 Python
Flask框架搭建虚拟环境的步骤分析
2019/12/21 Python
基于python实现微信好友数据分析(简单)
2020/02/16 Python
武汉高蓝德国际.net机试
2016/06/24 面试题
大学生职业生涯规划范文
2014/01/22 职场文书
索桥的故事教学反思
2014/02/06 职场文书
上课看小说检讨书
2014/02/22 职场文书
入党积极分子自我鉴定范文
2014/03/25 职场文书
《青山处处埋忠骨》教学反思
2014/04/22 职场文书
体育专业自荐书
2014/05/29 职场文书
2015法院个人工作总结范文
2015/05/25 职场文书
详解Vue的列表渲染
2021/11/20 Vue.js
Java线程的6种状态与生命周期
2022/05/11 Java/Android
python单向链表实例详解
2022/05/25 Python