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

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

公司项目前段时间须要实现手机拍照上传的功能,原本觉得用createObjectURL和canvas能够很轻松的实现,结果发现问题多多,特此记录下来。html

DEMO预览(需用新标签页打开)ios

图片预览

在IOS上,竖着拍照片时,图片预览会旋转90°,横着拍照就没问题,我实验了一下,在IOS上,只有当图片的分辨率过大会出现这种状况。git

最后实现图片预览效果借助了exif-jsmegapix-imageexif-js负责读取图片的EXIF信息,获取orientation信息,而后用megapix-image把图片数据渲染在img标签上,代码以下:github

import EXIF from '../utils/exif';
import MegaPixImage from '../utils/megapix-image';
     /**
     * 
     * @param file file对象
     * @param resImg 预览IMG标签
     * @returns {Promise}
     */
    renderPreviewImg(file, resImg) {
        return new Promise(function (resolve, reject) {
            EXIF.getData(file, _=> {
                var allMetaData = EXIF.getAllTags(file);
                var orientation = allMetaData.Orientation;

                var mpImg = new MegaPixImage(file);

                mpImg.render(resImg, {
                    maxWidth: 1024,
                    maxHeight: 1024,
                    // quality: 0.6,
                    orientation: orientation
                }, resolve);

            });
        });


    }

无刷新压缩上传

思路有两种:web

  1. 用canvas的toDataURL()API,直接将base64文本传递过去ajax

  2. 本身构造File对象,ajax上传canvas

第一种方法须要服务器端作工做,并且上传数据量会增大4/3,所以此方法只做为回退方案。api

第二种方法的原理是用Uint8Array来构造Blob,再使用formData上传。
这里要注意的是:ArrayBuffer不能被直接操做,必须经过typed array来存取,并且Blob的构造函数也是typed array服务器

完整代码以下:app

this.renderPreviewImg(file, resImg)
            .then(() => {

                try {
                    var binaryData = null;

                    if (!Blob || !ArrayBuffer || !Uint8Array) {
                        // alert(123);
                        binaryData = file;//若是不支持压缩,直接上传原始图片

                    } else {
                        //组装二进制
                        var base64Data = $(resImg).attr('src');
                        var byteString = atob(base64Data.split(',')[1]);
                        var ab = new ArrayBuffer(byteString.length);
                        var ia = new Uint8Array(ab);
                        for (var i = 0; i < byteString.length; i++) {
                            ia[i] = byteString.charCodeAt(i);
                        }
                        binaryData = new Blob([ia], {
                            "type": file.type
                        });

                    }

                    this.setState({
                        uploadProgress: 0
                    });

                    //组装formData
                    var fd = new FormData();
                    fd.append('file', binaryData, 'img.jpg');
                    fd.append('token', uploadToken);

                    console.log(fd);

                    return this.uploadBinaryDataToQiniu(fd, this.uploadSuccess.bind(this), this.handleUploadProgress.bind(this))


                } catch (e) {
                    alert(e.message);
                }
            }).catch(function (e) {
            console.log(e);
        })

参考文章

http://tgideas.qq.com/webplat...

http://blog.csdn.net/hsany330...

相关文章
相关标签/搜索