使用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的map与get方法详解
Nov 04 Javascript
把字符串按照特定的字母顺序进行排序的js代码
Jan 28 Javascript
详解JavaScript对Date对象的操作问题(生成一个倒数7天的数组)
Oct 01 Javascript
Js与Jq获取浏览器和对象值的方法
Mar 18 Javascript
js实现String.Fomat的实例代码
Sep 02 Javascript
jQuery实现简洁的轮播图效果实例
Sep 07 Javascript
微信小程序-详解数据缓存
Nov 24 Javascript
Bootstrap面板学习使用
Feb 09 Javascript
jquery实现的简单轮播图功能【适合新手】
Aug 17 jQuery
JavaScript深入V8引擎以及编写优化代码的5个技巧
Jun 24 Javascript
JSONP解决JS跨域问题的实现
May 25 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
Dec 09 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
一个颜色轮换的简单例子
2006/10/09 PHP
PHP 反射机制实现动态代理的代码
2008/10/22 PHP
PHP实现的英文名字全拼随机排号脚本
2014/07/04 PHP
Laravel5.* 打印出执行的sql语句的方法
2017/07/24 PHP
PHP7内核CGI与FastCGI详解
2019/04/14 PHP
关于laravel 日志写入失败问题汇总
2019/10/17 PHP
Ucren Virtual Desktop V2.0
2006/11/07 Javascript
phpwind放自动注册方法
2006/12/02 Javascript
js时间戳格式化成日期格式的多种方法
2013/11/11 Javascript
javascript实现单击和双击并存的方法
2014/12/13 Javascript
IE9+已经不对document.createElement向下兼容的解决方法
2015/09/14 Javascript
javascript中去除数组重复元素的实现方法【实例】
2016/04/12 Javascript
用AngularJS来实现监察表单按钮的禁用效果
2016/11/02 Javascript
BootStrap Table 后台数据绑定、特殊列处理、排序功能
2017/05/27 Javascript
vue + vuex todolist的实现示例代码
2018/03/09 Javascript
vue同步父子组件和异步父子组件的生命周期顺序问题
2018/10/07 Javascript
微信小程序实现上传图片裁剪图片过程解析
2019/08/22 Javascript
采用python实现简单QQ单用户机器人的方法
2014/07/03 Python
python采用requests库模拟登录和抓取数据的简单示例
2014/07/05 Python
Python运用于数据分析的简单教程
2015/03/27 Python
在Python中使用列表生成式的教程
2015/04/27 Python
Python实现从URL地址提取文件名的方法
2015/05/15 Python
为Python的Tornado框架配置使用Jinja2模板引擎的方法
2016/06/30 Python
Python实现的个人所得税计算器示例
2018/06/01 Python
详解python算法之冒泡排序
2019/03/05 Python
python实现快速文件格式批量转换的方法
2020/10/16 Python
AmazeUI 面板的实现示例
2020/08/17 HTML / CSS
捷克原创男装和女装购物网站:Bolf.cz
2018/04/28 全球购物
REISS美国官网:伦敦最受欢迎的时尚品牌
2019/08/16 全球购物
美国隐形眼镜网上商店:Lens.com
2019/09/03 全球购物
小学数学教学反思
2014/02/02 职场文书
公司拓展活动方案
2014/02/13 职场文书
大龄毕业生求职别忘职业规划
2014/03/11 职场文书
祖国在我心中演讲稿(小学生)
2014/09/23 职场文书
详解vue身份认证管理和租户管理
2021/05/25 Vue.js
mysql连接查询中and与where的区别浅析
2021/07/01 MySQL