使用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 相关文章推荐
使用dynatrace-ajax跟踪JavaScript的性能
Apr 12 Javascript
JavaScript 产生不重复的随机数三种实现思路
Dec 13 Javascript
去掉gridPanel表头全选框的小例子
Jul 18 Javascript
js中的push和join方法使用介绍
Oct 08 Javascript
jQuery简单实现网页选项卡特效
Nov 24 Javascript
ES6学习笔记之Set和Map数据结构详解
Apr 07 Javascript
jQuery插件FusionCharts绘制的2D条状图效果【附demo源码】
May 13 jQuery
详解windows下vue-cli及webpack 构建网站(三)使用组件
Jun 17 Javascript
Vue项目中添加锁屏功能实现思路
Jun 29 Javascript
Vue.js点击切换按钮改变内容的实例讲解
Aug 22 Javascript
Vue使用Ref跨层级获取组件的步骤
Jan 25 Vue.js
给原生html中添加水印遮罩层的实现示例
Apr 02 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使用CURL获取302跳转后的地址实例
2014/05/04 PHP
PHP+javascript制作带提示的验证码源码分享
2014/05/28 PHP
Laravel+Intervention实现上传图片功能示例
2019/07/09 PHP
收集的网上用的ajax之chat.js文件
2007/04/08 Javascript
jQuery AJAX回调函数this指向问题
2010/02/08 Javascript
JavaScript高级程序设计 XML、Ajax 学习笔记
2011/09/10 Javascript
js弹出的对话窗口永远保持居中显示
2012/12/15 Javascript
顶部缓冲下拉菜单导航特效的JS代码
2013/08/27 Javascript
js综合应用实例简单的表格统计
2013/09/03 Javascript
使用nodejs、Python写的一个简易HTTP静态文件服务器
2014/07/18 NodeJs
JavaScript实现大数的运算
2014/11/24 Javascript
jQuery中unbind()方法用法实例
2015/01/19 Javascript
在浏览器中打开或关闭JavaScript的方法
2015/06/03 Javascript
form+iframe解决跨域上传文件的方法
2016/11/18 Javascript
JavaScript中return用法示例
2016/11/29 Javascript
AngularJS封装$http.post()实例详解
2017/05/06 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
vue-ajax小封装实例
2017/09/18 Javascript
echarts饼图扇区添加点击事件的实例
2017/10/16 Javascript
Node做中转服务器转发接口
2017/10/18 Javascript
解决iview打包时UglifyJs报错的问题
2018/03/07 Javascript
axios 处理 302 状态码的解决方法
2018/04/10 Javascript
vue中的自定义分页插件组件的示例
2018/08/18 Javascript
微信小程序 自定义弹窗实现过程(附代码)
2019/12/05 Javascript
vue ssr+koa2构建服务端渲染的示例代码
2020/03/23 Javascript
Vue elementui字体图标显示问题解决方案
2020/08/18 Javascript
python改变日志(logging)存放位置的示例
2014/03/27 Python
python实现n个数中选出m个数的方法
2018/11/13 Python
python3实现名片管理系统
2020/11/29 Python
Python unittest单元测试框架实现参数化
2020/04/29 Python
基于FME使用Python过程图解
2020/05/13 Python
python实现按日期归档文件
2021/01/30 Python
美国高端婴童品牌:Hanna Andersson
2016/10/30 全球购物
普通大学毕业生自荐信
2013/11/04 职场文书
学术研讨会欢迎词
2015/01/26 职场文书
导游词之丹东鸭绿江
2019/10/24 职场文书