使用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 相关文章推荐
Prototype使用指南之hash.js
Jan 10 Javascript
JS字符串函数扩展代码
Sep 13 Javascript
javascript nextSibling 与 getNextElement(node) 使用介绍
Oct 13 Javascript
js处理php输出时间戳对不上号的解决方法
Jun 20 Javascript
JavaScript面向对象编写购物车功能
Aug 19 Javascript
微信小程序 九宫格实例代码
Jan 21 Javascript
Bootstrap 表单验证formValidation 实现表单动态验证功能
May 17 Javascript
利用jsonp与代理服务器方案解决跨域问题
Sep 14 Javascript
关于Vue单页面骨架屏实践记录
Dec 13 Javascript
vue实现的上传图片到数据库并显示到页面功能示例
Mar 17 Javascript
cnpm加速Angular项目创建的方法
Sep 07 Javascript
layui 富文本图片上传接口与普通按钮 文件上传接口的例子
Sep 23 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
ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼
2015/03/25 PHP
PHP判断手机是IOS还是Android
2015/12/09 PHP
基于PHP的微信公众号的开发流程详解
2020/08/07 PHP
各种常用浏览器getBoundingClientRect的解析
2009/05/21 Javascript
jquery ajax return没有返回值的解决方法
2011/10/20 Javascript
jQuery标签编辑插件Tagit使用指南
2015/04/21 Javascript
JS实现点击按钮后框架内载入不同网页的方法
2015/05/05 Javascript
JQuery节点元素属性操作方法
2015/06/11 Javascript
网站申请不到支付宝接口、微信接口,免接口收款实现方式几种解决办法
2016/12/14 Javascript
原生JS实现不断变化的标签
2017/05/22 Javascript
详解cordova打包成webapp的方法
2017/10/18 Javascript
微信小程序支付PHP代码
2018/08/23 Javascript
在node中使用jwt签发与验证token的方法
2019/04/03 Javascript
vue安装遇到的5个报错及解决方法
2019/06/12 Javascript
微信小程序获取用户绑定手机号方法示例
2019/07/21 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
js实现简易拖拽的示例
2020/10/26 Javascript
Vue+Spring Boot简单用户登录(附Demo)
2020/11/12 Javascript
nodejs+express最简易的连接数据库的方法
2020/12/23 NodeJs
Python如何判断数独是否合法
2016/09/08 Python
python中OrderedDict的使用方法详解
2017/05/05 Python
Python cookbook(数据结构与算法)将多个映射合并为单个映射的方法
2018/04/19 Python
Python基于SMTP协议实现发送邮件功能详解
2018/08/14 Python
Mac在python3环境下安装virtualwrapper遇到的问题及解决方法
2019/07/09 Python
python超时重新请求解决方案
2019/10/21 Python
pytorch模型存储的2种实现方法
2020/02/14 Python
python如何把字符串类型list转换成list
2020/02/18 Python
在django中使用post方法时,需要增加csrftoken的例子
2020/03/13 Python
html5文本内容_动力节点Java学院整理
2017/07/11 HTML / CSS
Html5 Geolocation获取地理位置信息实例
2016/12/09 HTML / CSS
公司授权委托书样本
2014/09/15 职场文书
2014财务年度工作总结
2014/11/11 职场文书
MBA推荐信怎么写
2015/03/25 职场文书
浅析InnoDB索引结构
2021/04/05 MySQL
OpenCV-Python使用cv2实现傅里叶变换
2021/06/09 Python
Java 中的 Lambda List 转 Map 的多种方法详解
2022/07/07 Java/Android