关于利用input file 移动端上传的问题处理

2018-08-24 16:42:00 3358 4 编辑:深正互联 来源:互联网

近期处理了一个html5在移动端上传问题,通过input file组件可以实现点击调用移动端系统拍照和上传功能,基于React写法如下 

<input onChange={this.props.uploadFile} type="file" accept="image/*" {...capture}/>

解释:capture 的取值如果为 camera 则直接调用摄像头拍照,拍照或者选择相册完成后触发 uploadFile 方法读取图像数据做进一步操作。uploadFile 方法如下: 

// 获取本地图像

uploadFile(e, type) {

    e.stopPropagation();

    let _this = this;

    let file = e.target.files[0];

    

    // 过滤非图片格式

    if (file && !/image\/\w+/.test(file.type)) {

        pageConfig.alert("文件必须为图片!");

        return false;

    }

    

    let reader = new FileReader();

    let filesize = Math.round(file.size / 1024);

    let mId = this.props.imgState.target;

    reader.onload = function () {

        let url = reader.result; // 压缩图片            

        _compass(url, filesize);

    }

    reader.readAsDataURL(file);  // 将文件转为base64


    function _compass(res, filesize) {

            let max = 100;

            if (filesize > max) {

                // 如果图片大于100K,则需要压缩;

                let img = new Image();

                let maxW = window.screen.availWidth * window.devicePixelRatio / 2 // 设备宽度

                img.onload = () => {

                    let canvas = document.createElement('canvas');

                    let ctx = canvas.getContext('2d');

                    if (img.width > maxW) {

                        img.height *= maxW / img.width;  // 同比例缩小

                        img.width = maxW;

                    }


                    canvas.width = img.width;

                    canvas.height = img.height;

                    ctx.clearRect(0, 0, ctx.width, ctx.height);

                    ctx.drawImage(img, 0, 0, img.width, img.height);

                    let dataUrl = canvas.toDataURL('image/jpeg', .95); //压缩质量


                    // 开始上传照片

                    that.startUploadPhoto(type, mId, dataUrl);

                }

                img.src = res;

            } else {

                // 开始上传

                that.startUploadPhoto(type, mId, res);

            }

        }

}


问题比较好处理,我们可根据 web 的 FileReader api来获取图片文件的base64位数据,结合 canvas 绘图对base64位数据进行压缩操作后上传到服务器


然而在测试过程中发现,在ios上如果是竖拍,显示出来却是横着的,也就是ios的Safari把照片自动旋转了。这个怎么处理呢,把获得的图像转过来就好了。这里用到一个辅助的库:exif.js, exif 能够获取到图片的元数据,当然也包含了图片的方向信息(Orientation),我们可以根据这个信息对图片做转动处理,新增一个转动图像的方法,把代码优化一下:

uploadFile(e, type) {

    e.stopPropagation();

    let _this = this;

    let file = e.target.files[0];

    

    // 过滤非图片格式

    if (file && !/image\/\w+/.test(file.type)) {

    pageConfig.alert("文件必须为图片!");

    return false;

    }

    

    let reader = new FileReader();

    let filesize = Math.round(file.size / 1024);

    let mId = this.props.imgState.target;

    reader.onload = function () {

    let url = reader.result;

    canvasDataURL(url, filesize)

    }

    reader.readAsDataURL(file);  // 将文件转为base64

    

    

    //获取上传图片的Orientation并旋转

    function canvasDataURL(path) {

    var img = new Image();

    var canvas = document.createElement("canvas");

    let myBase64Img = '';

    img.onload = function () {

    EXIF.getData(this, function () {

    let imgOrientation = EXIF.getTag(this, 'Orientation');

    //如果方向角不为1,都需要进行旋转

    console.log('----Orientation-----', imgOrientation);

    if (imgOrientation != "" && imgOrientation != 1 && imgOrientation) {

    switch (imgOrientation) {

    case 6: //需要顺时针(向左)90度旋转

    myBase64Img = rotateImg(this, 'left', canvas);

    break;

    case 8: //需要逆时针(向右)90度旋转  

    myBase64Img = rotateImg(this, 'right', canvas);

    break;

    case 3: //需要180度旋转  

    myBase64Img = rotateImg(this, 'right', canvas); //转两次  

    myBase64Img = rotateImg(this, 'right', canvas);

    break;

    }

    } else {

    myBase64Img = rotateImg(this, 'none', canvas);

    }

    

    // 开始上传照片

    _this.startUploadPhoto(type, mId, myBase64Img);

    // _this.props.actions.queryImgState({ front: myBase64Img });

    });

    }

    img.src = path;

    }

    

    function rotateImg(img, direction, canvas) {

    //最小与最大旋转方向,图片旋转4次后回到原方向    

    var min_step = 0;

    var max_step = 3;

    if (img == null) return;

    

    // 图片原始尺寸

    var originWidth = img.width;

    var originHeight = img.height;

    // 最大尺寸限制,可通过国设置宽高来实现图片压缩程度

    var maxWidth = 800,

    maxHeight = 800;

    // 目标尺寸

    var targetWidth = originWidth,

    targetHeight = originHeight;

    // 图片尺寸超过400x400的限制

    if (originWidth > maxWidth || originHeight > maxHeight) {

    if (originWidth / originHeight > maxWidth / maxHeight) {

    // 更宽,按照宽度限定尺寸

    targetWidth = maxWidth;

    targetHeight = Math.round(maxWidth * (originHeight / originWidth));

    } else {

    targetHeight = maxHeight;

    targetWidth = Math.round(maxHeight * (originWidth / originHeight));

    }

    }

    

    var height = targetHeight;

    var width = targetWidth;

    var step = 2;

    if (step == null) {

    step = min_step;

    }

    if (direction == 'right') {

    step++;

    //旋转到原位置,即超过最大值    

    step > max_step && (step = min_step);

    } else if (direction == 'none') {

    step = 10;

    } else {

    step--;

    step < min_step && (step = max_step);

    }

    //旋转角度以弧度值为参数    

    var degree = step * 90 * Math.PI / 180;

    var ctx = canvas.getContext('2d');

    ctx.clearRect(0, 0, targetWidth, targetHeight);

    switch (step) {

    case 0:

    canvas.width = width;

    canvas.height = height;

    ctx.drawImage(img, 0, 0, targetWidth, targetHeight);

    break;

    case 1:

    canvas.width = height;

    canvas.height = width;

    ctx.rotate(degree);

    ctx.drawImage(img, 0, -height, targetWidth, targetHeight);

    break;

    case 2:

    canvas.width = width;

    canvas.height = height;

    ctx.rotate(degree);

    ctx.drawImage(img, -width, -height, targetWidth, targetHeight);

    break;

    case 3:

    canvas.width = height;

    canvas.height = width;

    ctx.rotate(degree);

    ctx.drawImage(img, -width, 0, targetWidth, targetHeight);

    break;

    case 10: // 不旋转

    canvas.width = width;

    canvas.height = height;

    ctx.drawImage(img, 0, 0, targetWidth, targetHeight);

    break;

    }

    

    let dat = canvas.toDataURL("image/jpeg", 0.8);

    return dat;

    };


}


本站文章均为深正网站建设摘自权威资料,书籍,或网络原创文章,如有版权纠纷或者违规问题,请即刻联系我们删除,我们欢迎您分享,引用和转载,但谢绝直接搬砖和抄袭!感谢...
关注深正互联

15

技术从业经验

多一份方案,会有收获...

联系深正互联,免费获得专属《策划方案》及报价

在线咨询 微信交谈
拒绝骚扰,我们只想为给您带来一些惊喜...
多一份免费策划方案,总有益处。

请直接添加技术总监微信联系咨询