热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

通过HTML5移动开发实现图片压缩上传的功能-

这篇文章主要介绍了关于通过HTML5移动开发实现图片压缩上传的功能,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
这篇文章主要介绍了关于通过HTML5移动开发实现图片压缩上传的功能,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

移动端上传图片,用户一般都是上传手机相册中的图片,而现在手机的拍摄质量越来越高,一般单张照片的尺寸都在3M左右,因此需要在上传之前,先进行本地压缩。

H5活动已十分普遍,其中一种形式是让用户上传图片进行参与。移动端上传图片,用户一般都是上传手机相册中的图片,而现在手机的拍摄质量越来越高,一般单张照片的尺寸都在3M左右。若直接上传,十分耗流量,并且体验效果也不佳。因此需要在上传之前,先进行本地压缩。

接下来总结在h5活动的开发中图片压缩上传的功能,并标记其中踩过的几个坑,分享给大家:

小白区必看

对于移动端图片上传毫无概念的话,需要补充FileReader、Blob、FormData三个概念。

1.FileReader

定义

使用FileReader对象,web应用程序可以异步的读取存储在用户计算机上的文件(或者原始数据缓冲)内容,可以使用File对象或者Blob对象来指定所要处理的文件或数据.

方法

使用

var fileReader = new FileReader();
fileReader.Onload= function() {
    var url = this.result;
}
//or
fileReader.Onload= function(e) {
    var url = e.target.result;
}

2.Blob

BLOB(binary large object),二进制大对象,是一个可以存储二进制文件的容器。

3.FormData

利用FormData对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个”表单”.

正题

移动端图片压缩上传过程:

1)input file上传图片,使用FileReader读取用户上传的图片;

2)图片数据传入img对象,将img绘制到canvas上,再使用canvas.toDataURL进行压缩;

3)获取压缩后的base64格式图片数据,转成二进制,塞入formdata,最后通过xmlHttpRequest提交formdata;

1.获取图片数据

fileEle.Onchange= function() {
    if (!this.files.length) return;
    //以下考虑的是单图情况
    var _ua = window.navigator.userAgent;
    var _simpleFile = this.files[0];
    //判断是否为图片
    if (!/\/(?:jpeg|png|gif)/i.test(_simpleFile.type)) return;
    //插件exif.js获取ios图片的方向信息
    var _orientation;
    if(_ua.indexOf('iphone') > 0) {
        EXIF.getData(_simpleFile,function(){
            _orientation=EXIF.getTag(this,'Orientation');
        });
    }
    //1.读取文件,通过FileReader,将图片文件转化为DataURL,即data:img/png;base64,开头的url,可以直接放在image.src中;
    var _reader = new FileReader(),
        _img = new Image(),
        _url;
    _reader.Onload= function() {
        _url = this.result;
        _img.url = _url;
        _img.Onload= function () {
            var _data = compress(_img);
            uploadPhoto(_data, _orientation);
        };
    };
    _reader.readAsDataURL(_simpleFile);
};

2.压缩图片

/**
 * 计算图片的尺寸,根据尺寸压缩
 * 1. iphone手机html5上传图片方向问题,借助exif.js
 * 2. 安卓UC浏览器不支持 new Blob(),使用BlobBuilder
 * @param  {Object} _img         图片
 * @param  {Number} _orientation 照片信息
 * @return {String}              压缩后base64格式的图片
 */
function compress(_img, _orientation) {
    //2.计算符合目标尺寸宽高值,若上传图片的宽高都大于目标图,对目标图等比压缩;如果有一边小于,对上传图片等比放大。
    var _goalWidth = 750,                  //目标宽度
        _goalHeight = 750,                 //目标高度
        _imgWidth = _img.naturalWidth,     //图片宽度
        _imgHeight = _img.naturalHeight,   //图片高度
        _tempWidth = _imgWidth,            //放大或缩小后的临时宽度
        _tempHeight = _imgHeight,          //放大或缩小后的临时宽度
        _r = 0;                            //压缩比
    if(_imgWidth === _goalWidth && _imgHeight === _goalHeight) {
    } else if(_imgWidth > _goalWidth && _imgHeight > _goalHeight) {//宽高都大于目标图,需等比压缩
        _r = _imgWidth / _goalWidth;
        if(_imgHeight / _goalHeight <_r) {
            _r = _imgHeight / _goalHeight;
        }
        _tempWidth = Math.ceil(_imgWidth / _r);
        _tempHeight = Math.ceil(_imgHeight / _r);
    } else {
        if(_imgWidth <_goalWidth && _imgHeight <_goalHeight) {//宽高都小于
            _r = _goalWidth / _imgWidth;
            if(_goalHeight / _imgHeight <_r) {
                _r = _goalHeight / _imgHeight;
            }
        } else {
            if(_imgWidth <_goalWidth) {         //宽小于
                _r = _goalWidth / _imgWidth;
            } else{                              //高小于
                _r = _goalHeight / _imgHeight;
            }
        }
        _tempWidth = Math.ceil(_imgWidth * _r);
        _tempHeight = Math.ceil(_imgHeight * _r);
    }
    //3.利用canvas对图片进行裁剪,等比放大或缩小后进行居中裁剪
    var _canvas = e._$get(&#39;canvas-clip&#39;);
    if(!_canvas.getContext) return;
    var _cOntext= _canvas.getContext(&#39;2d&#39;);
    _canvas.width = _tempWidth;
    _canvas.height = _tempHeight;
    var _degree;
    //ios bug,iphone手机上可能会遇到图片方向错误问题
    switch(_orientation){
       //iphone横屏拍摄,此时home键在左侧
        case 3:
            _degree=180;
            _tempWidth=-_imgWidth;
            _tempHeight=-_imgHeight;
            break;
        //iphone竖屏拍摄,此时home键在下方(正常拿手机的方向)
        case 6:
            _canvas.width=_imgHeight;
            _canvas.height=_imgWidth; 
            _degree=90;
            _tempWidth=_imgWidth;
            _tempHeight=-_imgHeight;
            break;
        //iphone竖屏拍摄,此时home键在上方
        case 8:
            _canvas.width=_imgHeight;
            _canvas.height=_imgWidth; 
            _degree=270;
            _tempWidth=-_imgWidth;
            _tempHeight=_imgHeight;
            break;
    }
    if(window.navigator.userAgent.indexOf(&#39;iphone&#39;) > 0 && !!_degree) {
        _context.rotate(_degree*Math.PI/180);
        _context.drawImage(_img, 0, 0, _tempWidth, _tempHeight); 
    } else {
        _context.drawImage(_img, 0, 0, _tempWidth, _tempHeight);
    }
    //toDataURL方法,可以获取格式为"data:image/png;base64,***"的base64图片信息;
    var _data = _canvas.toDataURL(&#39;image/jpeg&#39;);
    return _data;
}

3.上传图片

/**
 * 上传图片到NOS
 * @param  {Object} _blog Blob格式的图片
 * @return {Void}
 */
function uploadPhoto(_data) {
    //4.获取canvas中的图片信息
    //window.atob方法将其中的base64格式的图片转换成二进制字符串;若将转换后的值直接赋值给Blob会报错,需Uint8Array转换:最后创建Blob对象;
    _data = _data.split(&#39;,&#39;)[1];
    _data = window.atob(_data);
    //如果不用ArrayBuffer,发送给服务器的图片格式是[object Uint8Array],上传失败...
    var _buffer = new ArrayBuffer(_data.length);
    var _ubuffer = new Uint8Array(_buffer);
    for (var i = 0; i <_data.length; i++) {
        _ubuffer[i] = _data.charCodeAt(i);
    }
    // 安卓 UC浏览器不支持 new Blob(),使用BlobBuilder
    var _blob;
    try {
        _blob = new Blob([_buffer], {type:&#39;image/jpeg&#39;});
    } catch(ee) {
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
        if (ee.name == &#39;TypeError&#39; && window.BlobBuilder) {
            var _bb = new BlobBuilder();
            _bb.append(_buffer);
            _blob = _bb.getBlob(&#39;image/jpeg&#39;);
        }
    }
    var _suffix = &#39;jpg&#39;;
    if(_blob.type === &#39;image/jpeg&#39;) {
        _suffix = &#39;jpg&#39;;
    }
    //获取NOStoken
    this.__cache._$requestDWRByGet({url: &#39;ImageBean.genTokens&#39;,param: [_suffix,&#39;&#39;,&#39;&#39;,&#39;&#39;,&#39;1&#39;],onload: function(_tokens) {
        _tokens = _tokens || [];
        var _token = _tokens[0];
        if(!_token || !_token.objectName || !_token.uploadToken){
            alert(&#39;token获取失败!&#39;);
            return false;
        }
        //上传图片到NOS
        var _objectName = _token.objectName,
            _uploadToken = _token.uploadToken,
            _bucketName = _token.bucketName;
        var _formData = new FormData();
        _formData.append(&#39;Object&#39;, _objectName);
        _formData.append(&#39;x-nos-token&#39;, _uploadToken);
        _formData.append(&#39;file&#39;,_blob);
        var _xhr;
        if (window.XMLHttpRequest) {
            _xhr = new window.XMLHttpRequest();
        } else if (window.ActiveXObject) {
            _xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }
        _xhr.Onreadystatechange= function() {
            if(_xhr.readyState === 4) {
                if((_xhr.status >= 200 && _xhr.status <300) || _xhr.status === 304) {
                    var _imgurl = "http://nos.netease.com/" + _bucketName + "/" + _objectName + "?imageView";
                    var _newUrl = mb.x._$imgResize(_imgurl, 750, 750, 1, true);
                    window.location.href = &#39;http://www.lofter.com/act/taxiu?op=effect&originImgUrl=&#39; + _newUrl;
                }
            }
        };
        _xhr.open(&#39;POST&#39;, &#39;http://nos.netease.com/&#39; + _bucketName, true);
        _xhr.send(_formData);
    }});
}

判断iphone拍摄图片方向的插件:exif

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!


推荐阅读
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了使用Python编写购物程序的实现步骤和代码示例。程序启动后,用户需要输入工资,并打印商品列表。用户可以根据商品编号选择购买商品,程序会检测余额是否充足,如果充足则直接扣款,否则提醒用户。用户可以随时退出程序,在退出时打印已购买商品的数量和余额。附带了完整的代码示例。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 本文介绍了一种图片处理应用,通过固定容器来实现缩略图的功能。该方法可以实现等比例缩略、扩容填充和裁剪等操作。详细的实现步骤和代码示例在正文中给出。 ... [详细]
author-avatar
好好地经历这每一天
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有