使用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 打造动态渐变按钮 详细图文教程
Apr 25 Javascript
JavaScript实现DIV层拖动及动态增加新层的方法
May 12 Javascript
浅谈关于JavaScript API设计的一些建议和准则
Jun 24 Javascript
javascript学习笔记之函数定义
Jun 25 Javascript
JavaScript引用类型和基本类型详解
Jan 06 Javascript
jquery常用的12个小功能
Jul 22 Javascript
非常实用的vue导航钩子
Mar 20 Javascript
Vue实例中生命周期created和mounted的区别详解
Aug 25 Javascript
jQuery实现打开网页自动弹出遮罩层或点击弹出遮罩层功能示例
Oct 19 jQuery
微信小程序实现批量倒计时功能
Nov 01 Javascript
javascript设计模式 ? 建造者模式原理与应用实例分析
Apr 10 Javascript
vue scroll滚动判断的实现(是否滚动到底部、滚动方向、滚动节流、获取滚动区域dom元素)
Jun 11 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
关于拼配咖啡,你要知道
2021/03/03 咖啡文化
简单的PHP留言本实例代码
2010/05/09 PHP
用PHP的超级变量$_GET获取HTML表单(Form) 数据
2011/05/07 PHP
WordPress中设置Post Type自定义文章类型的实例教程
2016/05/10 PHP
PHP 信号管理知识整理汇总
2017/02/19 PHP
Laravel5中Cookie的使用详解
2017/05/03 PHP
Laravel如何使用数据库事务及捕获事务失败后的异常详解
2017/10/23 PHP
Laravel使用原生sql语句并调用的方法
2019/10/09 PHP
PHP数组对象与Json转换操作实例分析
2019/10/22 PHP
jquery offset函数应用实例
2012/11/14 Javascript
javascript制作loading动画效果 loading效果
2014/01/14 Javascript
jQuery判断复选框是否勾选的原理及示例
2014/05/21 Javascript
浅析Node在构建超媒体API中的作用
2014/07/30 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
javaScript实现滚动新闻的方法
2015/07/30 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
JavaScript控制输入框中只能输入中文、数字和英文的方法【基于正则实现】
2017/03/03 Javascript
Nodejs读取文件时相对路径的正确写法(使用fs模块)
2017/04/27 NodeJs
Vue.js在使用中的一些注意知识点
2017/04/29 Javascript
Webpack devServer中的 proxy 实现跨域的解决
2018/06/15 Javascript
JS拖拽排序插件Sortable.js用法实例分析
2019/02/20 Javascript
layer提示框添加多个按钮选择的实例
2019/09/12 Javascript
详解vue3中组件的非兼容变更
2021/03/03 Vue.js
[44:26]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第二局
2016/03/03 DOTA
Python备份Mysql脚本
2008/08/11 Python
Python sys.path详细介绍
2013/10/17 Python
深入浅析Python2.x和3.x版本的主要区别
2018/11/30 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
英国女性时尚鞋类的潮流制造者:Koi Footwear
2018/10/19 全球购物
YSL圣罗兰美妆英国官网:Yves Saint Laurent Beauty UK
2019/08/03 全球购物
介绍一下grep命令的使用
2015/06/12 面试题
《雪地里的小画家》教学反思
2014/02/22 职场文书
小学班主任培训方案
2014/06/04 职场文书
python设置 matplotlib 正确显示中文的四种方式
2021/05/10 Python
python for循环赋值问题
2021/06/03 Python
docker-compose部署Yapi的方法
2022/04/08 Servers