使用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 $.ajax()取xml数据的小问题解决方法
Nov 20 Javascript
关于javascript中的typeof和instanceof介绍
Dec 04 Javascript
jquery插件如何使用 jQuery操作Cookie插件使用介绍
Dec 15 Javascript
JQuery查找DOM节点的方法
Jun 11 Javascript
jQuery常见的选择器及用法介绍
Dec 20 Javascript
js 博客内容进度插件详解
Feb 19 Javascript
Node.js 中exports 和 module.exports 的区别
Mar 14 Javascript
原生JavaScript实现的简单放大镜效果示例
Feb 07 Javascript
mpvue微信小程序的接口请求fly全局拦截代码实例
Nov 13 Javascript
vue el-table实现自定义表头
Dec 11 Javascript
在 Vue 中编写 SVG 图标组件的方法
Feb 24 Javascript
JavaScript 防盗链的原理以及破解方法
Dec 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
Chrome Web App开发小结
2014/09/04 PHP
Swoole源码中如何查询Websocket的连接问题详解
2020/08/30 PHP
根据出生日期自动取得星座的js代码
2010/07/20 Javascript
javascript验证上传文件的类型限制必须为某些格式
2013/11/14 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
2016/05/30 Javascript
jQuery实现公告新闻自动滚屏效果实例代码
2016/07/14 Javascript
connection reset by peer问题总结及解决方案
2016/10/21 Javascript
利用JQuery实现datatables插件的增加和删除行功能
2017/01/06 Javascript
使用Node.js实现RESTful API的示例
2017/08/01 Javascript
Node之简单的前后端交互(实例讲解)
2017/11/14 Javascript
浅谈React中组件间抽象
2018/01/27 Javascript
vue实现日历备忘录功能
2020/09/24 Javascript
高性能js数组去重(12种方法,史上最全)
2019/12/21 Javascript
JS document form表单元素操作完整示例
2020/01/13 Javascript
微信小程序国际化探索实现(附源码地址)
2020/05/20 Javascript
[01:32]寻找你心中的那团火 DOTA2 TI9火焰传递活动今日开启
2019/05/16 DOTA
详解Python判定IP地址合法性的三种方法
2018/03/06 Python
Python(Django)项目与Apache的管理交互的方法
2018/05/16 Python
Python3的介绍、安装和命令行的认识(推荐)
2018/10/20 Python
浅谈python的dataframe与series的创建方法
2018/11/12 Python
python下的opencv画矩形和文字注释的实现方法
2019/07/09 Python
Linux下通过python获取本机ip方法示例
2019/09/06 Python
python实现将一维列表转换为多维列表(numpy+reshape)
2019/11/29 Python
Python退出时强制运行一段代码的实现方法
2020/04/29 Python
Python趣味入门教程之循环语句while
2020/08/26 Python
中东地区最大的奢侈品市场:The Luxury Closet
2019/04/09 全球购物
安全大检查反思材料
2014/01/31 职场文书
新学期决心书
2014/03/11 职场文书
3.15国际消费者权益日主题活动活动总结
2014/03/16 职场文书
新闻人物通讯稿
2014/10/09 职场文书
自愿离婚协议书范文2014
2014/10/12 职场文书
个人年终总结结尾
2015/03/06 职场文书
担保贷款承诺书
2015/04/30 职场文书
写自招自荐信的绝招!
2019/04/19 职场文书
Nginx+Tomcat负载均衡多实例详解
2022/04/11 Servers
vue中data里面的数据相互使用方式
2022/06/05 Vue.js