使用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 相关文章推荐
javascript 触发事件列表 比较不错
Sep 03 Javascript
js设置document.domain实现跨域的注意点分析
May 21 Javascript
jquery点击切换背景色的简单实例
Aug 25 Javascript
Kindeditor单独调用多图上传实例
Jul 31 Javascript
parabola.js抛物线与加入购物车效果的示例代码
Oct 25 Javascript
vue.js项目中实用的小技巧汇总
Nov 29 Javascript
浅谈React 服务器端渲染的使用
May 08 Javascript
Vue中使用webpack别名的方法实例详解
Jun 19 Javascript
JS中判断字符串存在和非空的方法
Sep 12 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
Dec 11 jQuery
javascript设计模式 ? 代理模式原理与用法实例分析
Apr 16 Javascript
vue实现水波涟漪效果的点击反馈指令
May 31 Vue.js
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设置图片文件上传大小的具体实现方法
2013/10/11 PHP
ThinkPHP之R方法实例详解
2014/06/20 PHP
解决laravel groupBy 对查询结果进行分组出现的问题
2019/10/09 PHP
Javascript 网页黑白效果实现代码(兼容IE/FF等)
2010/04/23 Javascript
JQuery select标签操作代码段
2010/05/16 Javascript
js window.print实现打印特定控件或内容
2013/09/16 Javascript
超简单JS二级、多级联动的简单实例
2014/02/18 Javascript
JavaScript link方法入门实例(给字符串加上超链接)
2014/10/17 Javascript
60个很实用的jQuery代码开发技巧收集
2014/12/15 Javascript
深入了解JavaScript中的Symbol的使用方法
2015/07/28 Javascript
JavaScript实现广告弹窗效果
2016/08/09 Javascript
BootStrap 可编辑表Table格
2016/11/24 Javascript
工厂模式在JS中的实践
2017/01/18 Javascript
JS中静态页面实现微信分享功能
2017/02/06 Javascript
详解vue-cli + webpack 多页面实例应用
2017/04/25 Javascript
在一个页面实现两个zTree联动的方法
2017/12/20 Javascript
angular1.x ui-route传参的三种写法小结
2018/08/31 Javascript
如何解决webpack-dev-server代理常切换问题
2019/01/09 Javascript
Vue+Django项目部署详解
2019/05/30 Javascript
JavaScript事件委托实现原理及优点进行
2020/08/29 Javascript
详解python 发送邮件实例代码
2016/12/22 Python
深入理解Django中内置的用户认证
2017/10/06 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
Python推导式简单示例【列表推导式、字典推导式与集合推导式】
2018/12/04 Python
Python实现一个数组除以一个数的例子
2019/07/20 Python
python实现爱奇艺登陆密码RSA加密的方法示例详解
2020/05/27 Python
pycharm不以pytest方式运行,想要切换回普通模式运行的操作
2020/09/01 Python
波兰多品牌运动商店:StreetStyle24.pl
2020/09/22 全球购物
校运会入场式解说词
2014/02/10 职场文书
公司门卫岗位职责
2014/03/15 职场文书
2014年五一劳动节社区活动总结
2014/04/14 职场文书
个人授权委托书
2014/09/15 职场文书
小学语文教师年度考核个人总结
2015/02/05 职场文书
学历证明样本
2015/06/16 职场文书
小学2016年第十八届推普周活动总结
2016/04/05 职场文书
Python自然语言处理之切分算法详解
2021/04/25 Python