使用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 相关文章推荐
封装好的省市地区联动控件附下载
Aug 13 Javascript
文本链接逐个出现的js脚本
Dec 12 Javascript
js下用层来实现select的title提示属性
Feb 23 Javascript
jQuery选择器querySelector的使用指南
Jan 23 Javascript
javascript常用的方法分享
Jul 01 Javascript
分享一个原生的JavaScript拖动方法
Sep 25 Javascript
Chrome浏览器的alert弹窗禁止再次弹出后恢复的方法
Dec 30 Javascript
js 实现获取name 相同的页面元素并循环遍历的方法
Feb 14 Javascript
微信小程序自定义导航隐藏和显示功能
Jun 13 Javascript
了解前端理论:rscss和rsjs
May 23 Javascript
jQuery实现提交表单时不提交隐藏div中input的方法
Oct 08 jQuery
vue学习笔记之Vue中css动画原理简单示例
Feb 29 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
PHP如何透过ODBC来存取数据库
2006/10/09 PHP
一个图形显示IP的PHP程序代码
2007/10/19 PHP
比较strtr, str_replace和preg_replace三个函数的效率
2013/06/26 PHP
php第一次无法获取cookie问题处理
2014/12/15 PHP
PHP微信开发之文本自动回复
2016/06/23 PHP
Ubuntu 16.04下安装PHP 7过程详解
2017/03/28 PHP
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
javascript之水平横向滚动歌词同步的应用
2007/05/07 Javascript
JavaScript面向对象编程
2008/03/02 Javascript
javascript preload&amp;lazy load
2010/05/13 Javascript
CSS(js)限制页面显示的文本字符长度
2012/12/27 Javascript
JS获取Table中td值的方法
2015/03/19 Javascript
AngularJS入门之动画
2016/07/27 Javascript
JavaScript注入漏洞的原理及防范(详解)
2016/12/04 Javascript
JS重载实现方法分析
2016/12/16 Javascript
JS优化与惰性载入函数实例分析
2017/04/06 Javascript
js弹性势能动画之抛物线运动实例详解
2017/07/27 Javascript
详解基于Vue+Koa的pm2配置
2017/10/24 Javascript
vue中element-ui表格缩略图悬浮放大功能的实例代码
2018/06/26 Javascript
Bootstrap Table中的多选框删除功能
2018/07/15 Javascript
Vue2.0 $set()的正确使用详解
2020/07/28 Javascript
[02:35]DOTA2超级联赛专访XB 难忘一年九冠称王
2013/06/20 DOTA
python 装饰器功能以及函数参数使用介绍
2012/01/27 Python
R vs. Python 数据分析中谁与争锋?
2017/10/18 Python
树莓派使用python-librtmp实现rtmp推流h264的方法
2019/07/22 Python
带你彻底搞懂python操作mysql数据库(cursor游标讲解)
2020/01/06 Python
python+gdal+遥感图像拼接(mosaic)的实例
2020/03/10 Python
django 前端页面如何实现显示前N条数据
2020/03/16 Python
PyQt使用QPropertyAnimation开发简单动画
2020/04/02 Python
Python word文本自动化操作实现方法解析
2020/11/05 Python
纯css3(无图片/js)制作的几个社交媒体网站的图标
2013/03/21 HTML / CSS
鱼油专家:Omegavia
2016/10/10 全球购物
意大利综合购物网站:Giordano Shop
2016/10/21 全球购物
论文评语大全
2014/04/29 职场文书
民主生活会批评与自我批评总结
2014/10/17 职场文书
python中使用 unittest.TestCase单元测试的用例详解
2021/08/30 Python