资讯专栏INFORMATION COLUMN

移动端H5图片上传的那些坑

Seay / 3053人阅读

摘要:上周做一个关于移动端图片压缩上传的功能。利用,进行图片的压缩,得到图片的的值上传文件。

上周做一个关于移动端图片压缩上传的功能。期间踩了几个坑,在此总结下。

大体的思路是,部分API的兼容性请参照caniuse:

利用FileReader,读取blob对象,或者是file对象,将图片转化为data uri的形式。

使用canvas,在页面上新建一个画布,利用canvas提供的API,将图片画入这个画布当中。

利用canvas.toDataURL(),进行图片的压缩,得到图片的data uri的值

上传文件。

步骤1当中,在进行图片压缩前,还是对图片大小做了判断的,如果图片大小大于200KB时,是直接进行图片上传,不进行图片的压缩,如果图片的大小是大于200KB,则是先进行图片的压缩再上传:

    
    var fileChooser = document.getElementById("choose"),
        maxSize = 200 * 1024;   //200KB
    fileChoose.change = function() {
        var file = this.files[0],   //读取文件
            reader = new FileReader();
            
            reader.onload = function() {
                var result = this.result,   //result为data url的形式
                    img = new Image(),
                    img.src = result;
                    
                    
                if(result.length < maxSize) {  
                    imgUpload(result);      //图片直接上传
                } else {
                    var data = compress(img);    //图片首先进行压缩
                    imgUpload(data);                //图片上传
                }
            }
            
            reader.readAsDataURL(file);
    }

步骤2,3:

    var canvas = document.createElement("canvas"),
        ctx = canvas.getContext("2d");
        
    function compress(img) {
        canvas.width = img.width;
        canvas.height = img.height;
        
        //利用canvas进行绘图
        
        //将原来图片的质量压缩到原先的0.2倍。
        var data = canvas.toDataURL("image/jpeg", 0.2); //data url的形式
        
        return data;
    }

在利用canvas进行绘图的过程中,IOS图片上传过程中,存在着这样的问题:

当你竖着拿手机的时候,拍完照,上传图片时,会出现照片自动旋转的情况,而横着拍照并上传图片时不会出现这个问题。这个时候如果想纠正图片自动旋转的情况,将图片转化为二进制的数据(使用了binaryajax.js),方便获取图片的exif信息,通过获取exif的信息来确定图片旋转的角度(使用了exif.js),然后再进行图片相应的旋转处理。解决方法请戳我

IOS中,当图片的大小大于 2MB时,会出现图片压扁的情况,这个时候需要重置图片的比例。解决方法请戳我

利用FileReader,读取图片的过程需要花费一定时间,将图片数据注入到canvas画布中需要一定时间,图片压缩的过程中,图片越大,CPU计算消耗的时间也越长,可能会出现顿卡的情况。总之,就是这个过程当中需要花费一定时间。

IOS8.1的版本中有个FileReader的bug: FileReader读取的图片转化为Base64时,字符串为空,具体的问题描述请戳我

步骤4,文件上传有2种方式:

将图片转化为base64

将图片数据转为Blob对象,使用FormData上传文件

方式1可以通过xhr ajax或者xhr2 FormData进行提交。

方法2这里就有个大坑了。具体描述请戳我

简单点说就是:Blob对象是无法注入到FormData对象当中的。

当你拿到了图片的data uri数据后,将其转化为Blob数据类型

    var ndata = compress(img);
    ndata = window.atob(ndata); //将base64格式的数据进行解码
    
    //新建一个buffer对象,用以存储图片数据
    var buffer = new Uint8Array(ndata.length);
    for(var i = 0; i < text.length; i++) {
        buffer[i] = ndata.charCodeAt(i);
    }
    
    //将buffer对象转化为Blob数据类型
    var blob = getBlob([buffer]);
    
    var fd = new FormData(),
        xhr = new XMLHttpRequest();
    fd.append("file", blob);
    
    xhr.open("post", url);
    xhr.onreadystatechange = function() {
        //do something
    }
    xhr.send(fd);

在新建Blob对象中有需要进行兼容性的处理,特别是对于不支持FormData上传blob的andriod机的兼容性处理。具体的方法请戳我
主要实现的细节是通过重写HTTP请求。

2月19日更新

在安卓机器中,部分4.x的机型, 在webview里面对file对象进行了阉割,比如你拿不到file.type的值。

2月22日更新

Android4.4由于系统WebViewopenFileChooser接口更改,导致无法选择文件,从而导致无法上传文件. bug描述请戳我

封装好的github库,请戳我,如果觉得文章不错,请不要吝啬你的star~~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90837.html

相关文章

  • H5拍照、预览、压缩、上传记录

    摘要:拍照预览压缩上传采坑记录公司项目前段时间需要实现手机拍照上传的功能,本来以为用和可以很轻松的实现,结果发现问题多多,特此记录下来。完整代码如下如果不支持压缩,直接上传原始图片组装二进制组装参考文章 H5拍照、预览、压缩、上传采坑记录 公司项目前段时间需要实现手机拍照上传的功能,本来以为用createObjectURL和canvas可以很轻松的实现,结果发现问题多多,特此记录下来。 DE...

    gself 评论0 收藏0
  • FED之必备技能

    摘要:在我们深入研究这项新鲜的技术之前,让我们先快速的复习原理的相关知识。同时,希望本文能对大家有所帮助。工欲善其事,必先利其器。 flex.css快速入门,极速布局 什么是flex.css? css3 flex 布局相信很多人已经听说过甚至已经在开发中使用过它,但是我想我们都会有一个共同的经历,面对它的各种版本,各种坑,傻傻的分不清楚,flex.css就是对flex布局的一种封装,通过简洁...

    Zachary 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<