资讯专栏INFORMATION COLUMN

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

gself / 2700人阅读

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

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

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

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

图片预览

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

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

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);

            });
        });


    }
无刷新压缩上传

思路有两种:

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

自己构造File对象,ajax上传

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

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

完整代码如下:

     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...

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

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

相关文章

  • H5拍照、选择图片上传组件核心

    摘要:决定自己写一个移动端图片上传组件。允许多选,加上事件的回调函数。在的回调函数中,我们能通过拿到所选择的文件,但是文件是无法展示在页面上的,通常的做法是使用转为然后展示在页面上。 背景 前段时间项目重构,改成SSR的项目,但之前用的图片选择上传组件不支持SSR(server-side-render)。遂进行了调研,发现很多的工具。但有的太大,有的使用麻烦,有的不满足使用需求。决定自己写一...

    Guakin_Huang 评论0 收藏0
  • 关于手机端拍照上传图片的问题

    摘要:关于移动端拍照上传图片的解决方案场景产品要求用户拍一张身份证和一张人像,然后后台调用商用接口比对证件和人像的匹配度。缺点手机拍照图片过大,压缩后,图片依然大,没上传一次花费时间过长,最后再调用接口比对时间花费也长。 关于移动端拍照上传图片的解决方案 场景 产品要求用户拍一张身份证和一张人像,然后后台php调用商用接口比对证件和人像的匹配度。showImg(https://segment...

    jifei 评论0 收藏0

发表评论

0条评论

gself

|高级讲师

TA的文章

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