七牛直伝の書類

9606 ワード

公式APIアドレス:https://developer.qiniu.com/kodo/sdk/1283/javascript
七牛がJavaScript上传のプラグインを提供しているので、本稿ではこのプラグインを用いて七牛直伝を実現します.
1.7牛のアップロード証明書を取得する
  • はアリ雲OSS直伝と違って、七牛は一つのtokenを取得すればいいです.
  • は、バックエンドの協力を必要とし、インターフェースを提供する.
  • は、取得と保存のタイミングに注意して、有効期限切れの記録に基づいてsessionStorageを記録したほうがいいです.要求の回数を減らすことができますし、アップロード時の証明書の有効性も保証できます.
  • 取得tokenフロー:
  • (1)token取得要求を送信する-->(2)tokenを得てローカルに保存し、その後の直伝-->(3)tokenパラメータを持って七牛に要求を送信し、直伝画像-->(4)アップロードに成功したら、七牛は該当するピクチャアドレスに戻る(この住所の後続は一定の規則に従って後端に送られる必要がある)
  • 取得token
  • /**
        *          token (          )
        * @returns {Promise.}
    */
    const getUploadToken = () => {
        http.post('getUploadToken').then(res => {
            if (res.code === 200) {
                this.isPull = false;
                const expireTime = 30 * 60 * 1000; //     ,    (ms)
                sessionStorage.setItem('uploadToken', res.data.upload_token);
                sessionStorage.setItem('uploadTokenExpireTime', new Date().getTime() + expireTime); //    token     
                sessionStorage.setItem('imgURL', res.data.image_url); //       
            } else {
                //         
                this.errorHandler(res);
            }
        }).catch(() => {
            console.log('error');
        });
    }
    
    
    2.画像処理
  • ここで使用されるqiniu.min.jsは、画像のクロップ、スケーリング、回転などの機能も備えている.興味があるなら、この文書を見てもいいです.七牛写真高級処理
  • ここでは自分が実現した画像の簡単な処理を紹介します.
    (1)圧縮画像はiOS上に回転の問題があり、先に処理する必要があり、ここにexif-jsが導入されている.
    import Exif from 'exif-js'
    
    
    (2)画像の回転
    /**
     *  iOS     
     * @param img    
     * @param direction     
     * @param canvas   
     */
    const rotateImg = (img, direction, canvas) => {
        //          ,    4       
        const min_step = 0;
        const max_step = 3;
        if (img === null) return;
        // img           img        ,     
        let height = img.height;
        let width = img.width;
        let step = 2;
        if (step === null) {
            step = min_step;
        }
        if (direction === 'right') {
            step++;
            //       ,      
            step > max_step && (step = min_step);
        } else {
            step--;
            step < min_step && (step = max_step);
        }
        //            
        let degree = step * 90 * Math.PI / 180;
        let ctx = canvas.getContext('2d');
        switch (step) {
            case 0:
                canvas.width = width;
                canvas.height = height;
                ctx.drawImage(img, 0, 0);
                break;
            case 1:
                canvas.width = height;
                canvas.height = width;
                ctx.rotate(degree);
                ctx.drawImage(img, 0, -height);
                break;
            case 2:
                canvas.width = width;
                canvas.height = height;
                ctx.rotate(degree);
                ctx.drawImage(img, -width, -height);
                break;
            case 3:
                canvas.width = height;
                canvas.height = width;
                ctx.rotate(degree);
                ctx.drawImage(img, -width, 0);
                break;
        }
    }
    
    
    (3)画像圧縮
    /*
     * canvas     
     * @param img   
     * @param Orientation     
     * @returns ndata       
    */
    const compress = (img, Orientation) => {
        let canvas = document.createElement("canvas");
        let ctx = canvas.getContext('2d');
        //  canvas
        let tCanvas = document.createElement("canvas");
        let tctx = tCanvas.getContext("2d");
        let initSize = img.src.length;
        let width = img.width;
        let height = img.height;
        let time = new Date().getTime();
        //            ,           400   
        let ratio;
        if ((ratio = width * height / 4000000) > 1) {
            console.log("  400   ");
            ratio = Math.sqrt(ratio);
            width /= ratio;
            height /= ratio;
        } else {
            ratio = 1;
        }
        canvas.width = width;
        canvas.height = height;
        //    
        ctx.fillStyle = "#fff";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        //         100        
        let count;
        if ((count = width * height / 1000000) > 1) {
            console.log("  100W  ");
            count = ~~(Math.sqrt(count) + 1); //          
            //           
            let nw = ~~(width / count);
            let nh = ~~(height / count);
            tCanvas.width = nw;
            tCanvas.height = nh;
            for (let i = 0; i < count; i++) {
                for (let j = 0; j < count; j++) {
                    tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
                    ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
                }
            }
        } else {
            ctx.drawImage(img, 0, 0, width, height);
        }
        //   ios              
        if (Orientation != '' && Orientation != 1) {
            switch (Orientation) {
                case 6: //      (  )90   
                    this.rotateImg(img, 'left', canvas);
                    break;
                case 8: //      (  )90   
                    this.rotateImg(img, 'right', canvas);
                    break;
                case 3: //   180   
                    this.rotateImg(img, 'right', canvas);//   
                    this.rotateImg(img, 'right', canvas);
                    break;
            }
        }
        //       
        let ndata = canvas.toDataURL('image/jpeg', 0.1);
        console.log('   :' + initSize);
        console.log('   :' + ndata.length);
        console.log('   :' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
        tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
        console.log('    :' + (new Date().getTime() - time) + 'ms');
        return ndata;
    }
    
    
    (4)base 64ピクチャをBlobオブジェクトに符号化する
    /*
     *   base64        Blob   
     * @dataURI    base64   
     * @returns {Blob}
    */
    const dataURItoBlob = (dataURI) => {
        let byteString = atob(dataURI.split(',')[1]);
        let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
        let ab = new ArrayBuffer(byteString.length);
        let ia = new Uint8Array(ab);
        for (let i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
        return new Blob([ab], {type: mimeString});
    }
    
    
    3.7牛のアップロード方法
    (1)七牛の導入
    import * as qiniu from 'qiniu-js'
    
    
    (2)アップロード方法
     /**
     *      
     *  @param base64String     (Blob   base64String)
     */
    const qiniuUpload = (base64String) => {
         //                base64String,            Blob   ,         Blob   ,              
         let file;
         if (typeof base64String === 'string'){
             file = this.dataURItoBlob(base64String);
         } else {
             file = base64String;
         }
        //        
        //           (Blob),          (        ,          ,        ),       token
        const observable = qiniu.upload(file, file.name, sessionStorage.getItem('uploadToken'), {
            fname: file.name,
            params: {},
            mimeType: [] || null
        }, {
             useCdnDomain: true, // cdn
             unique_names: false, //     
             region: qiniu.region.z0 //            
        });
    
        //    Promise,         
        return new Promise( (resolve, reject) => {
            const subscription = observable.subscribe({
                next (res) {
                    //      ,       ,    ,       
                },
                error (err) {
                    console.log('  ');
                    console.log(err);
                },
                complete (res) {
                    //    ,    
                    console.log('    ');
                    resolve({
                        base64String: base64String,
                        imgUrl: sessionStorage.getItem('imgURL')+'/'+ res.key
                    });
                }
            });
        });
    }
    
    
    4.前にしたのは全部準備作業です.本当にアップロードをトリガしたのはここです.
    /*
     *    (   change     )
     * @param file    Blob   ,  change           
     * @returns {Promise}
    */
    const readFiles = (file) => {
        //      token     
        async function getToken() {
            if (new Date().getTime() > sessionStorage.getItem('uploadTokenExpireTime')) {
                getUploadToken();
            }
        }
    
        return getToken().then(() => {
            let Orientation;
            let base64String = '';
            const reader = new FileReader(); //    FileReader        render        
    
            //        base64   
            base64String = reader.readAsDataURL(file);
            // iOS     
            Exif.getData(file, function () {
                Orientation = Exif.getTag(this, 'Orientation');
            });
    
            //        
            return new Promise(resolve => {
                reader.onloadend = function () {
                    let result = this.result;
                    let img = new Image();
                    img.src = result;
                    //        100K,      ,      
                    if (this.result.length <= (100 * 1024)) {
                        resolve(qiniuUpload(result));
                    } else {
                        img.onload = function () {
                            let data = that.compress(img, Orientation);
                            resolve(that.qiniuUpload(data));
                        }
                    }
                };
            });
        });
    }
    
    
    低バージョンブラウザの使用にはある程度の互換性があります.
    上の方法はes 6文法を使いました.
    上の方法は運んで直接使うことができません.少し変更しなければなりません.
    5.readFileを使ったら、七牛のコールバックデータを返します.readFile().then(res => {...})に該当操作を書けばいいです.