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

相關文章
相關標籤/搜索