jqに基づいてAPKファイルのドラッグアップロードを実現し、jsはAPK情報を解析する

13785 ワード

テクノロジースタック
  • jquery
  • ファイルアップロード:jquery.file upload,githubドキュメント
  • apkファイル解析:app-info-parser,githubドキュメント
  • 参考:フロントエンド解析ipa、apkインストールパッケージ情報-app-info-parser
    サポート機能
  • クリックまたはドラッグアップロードapkファイル
  • ファイルタイプおよびファイルサイズのチェック
  • js解析apkファイル情報は、アップロードインタフェースを介してバックエンド
  • に送信する.
  • はアップロード中に
  • のアップロードをキャンセルすることをサポートする.
  • アップロード成功表示アップロード情報
  • をサポート
  • は解析、アップロードなどの友好的なヒント
  • をサポートする.
  • は、履歴(アップロードされたすべてのファイル)から
  • を選択することをサポートします.
  • は、例えば、偽ファイル処理をサポートする.txtファイルを.apkファイル
  • アップロードの進捗状況のリアルタイム更新、パーセント、B/s
  • ドラッグしてドラッグエリアに入ると、
  • がハイライト表示されます.
    demoプレビュー
    説明
    アップロードインタフェースにはバックエンドインタフェースのサポートが必要なため、静的ページで完全なインタラクションを表示することはできません.そこで、ここにプレビュー図を置きます.
    gif図が大きすぎるのを避けるために、クリックアップロードに成功した場合だけを録画しました.他の状況はスクリーンを録画していないので、自分でdemoをダウンロードして、バックエンド環境を構築して、アップロードインタフェースをシミュレートして実現することができます.demoではphp言語シミュレーションでアップロードインタフェースを実現した.ソースアドレス
    難点
  • js解析APKファイル情報
  • ドラッグアップロード、クリックアップロードとドラッグアップロードバインド
  • アップロードする前にAPKファイル情報を知らないため、アップロード操作を実行する過程で解析したファイル情報をパラメータとしてアップロードインタフェースに配置する必要がある
  • .
  • アップロード中に
  • アップロードをキャンセル
  • 偽ファイル解析エラー処理、jsモニタコンソールエラー
  • インプリメンテーション
    1.js解析APKファイル情報
    調べたところ、APKファイルの本質は圧縮パッケージであり、XMLファイル、資産、クラスファイルの山が含まれていることがわかりました.JAvascriptはAPKファイル情報を解析し、まず解凍し、その中の関連ファイルを読み取ることで、ファイル情報を得ることができます.
    難点は解凍で、参考の基本はnode環境を借りる必要があります.現在メンテナンスされているシステムはjquery環境に基づいているためです.そこで,最終的にipa,apkインストールパッケージ情報であるapp-info-parserをフロントエンド解析するスキームを採用し,問題をうまく解決した.ここで著者に感謝します.
     // apk     
    var parser = new AppInfoParser(data.files[0]);
    parser.parse().then(function(result) {
        uploadMod.doms.uploadErr.html('');
        var appInfo = result.application || {};
        var formAppInfo = {
            name: appInfo.label ? (Array.isArray(appInfo.label) ? appInfo.label[0] : appInfo.label) : '',
            package: result.package,
            version: result.versionName,
            version_code: result.versionCode
        };
        
        //         ...
    }).catch(function (err) {
        uploadMod.doms.uploadErr.html('      ,     ');
    });

    説明:
  • app-info-parserの下位層がasync構文を使用しているため、IEの下では互換性がありません.firefox、chromeでは正常です.
  • 偽APKファイルをアップロードし、処理できません.jsスクリプトはエラーを報告します:File format is not recognized..現在考えられている解決策はjsがエラーを傍受し、処理することである.もっといい考えがあれば、@私を歓迎します.ここで前もって感謝します.
  • // console.error()     
    consoleError = window.console.error;
    window.console.error = function () {
        consoleError && consoleError.apply(window, arguments);
        for (var info in arguments) {
            if (arguments[info] == 'File format is not recognized.') {
                $('#app_parse').html('

    APK , , , ,

    '); setTimeout(function () { history.go(0); }, 3000); return false; } } };

    ページの他のエラーを回避するために、スクリプトが実行できないため、ページのリフレッシュを行いました.
    2.ドラッグアップロード、クリックアップロードとドラッグアップロードを一緒にバインド
    この機能を行う前に、ドラッグアップロードはH 5のドラッグアップ機能やオリジナルjsのfileファイルアップロードで実現できると思いますが、互換性の問題を処理する必要があります.その後、システムにjqueryが導入されたと考えられた.file uploadライブラリは、ドキュメントをめくってドラッグアップロードをサポートしています.そのため、このライブラリを使用してドラッグアップロード機能を実現します.
    htmlレイアウトは次のとおりです.

    APK , 300 MB


    どのようにドラッグ&ドロップを一緒に処理して、1つのアップロード方法で実現して、別々に2回実現する必要はありませんか?
    考えは,外層コンテナをクリックし,inputクリックイベントをトリガーすることである.前提はinputクリックイベントを実現し、外層にもクリックイベントがあるため、バブルイベントを阻止する必要がある.
    $('body').on('click', '#upload_input', function (e) {
        e.stopPropagation();
        uploadMod.methods.fileUpload();
    }).on('click drop dragenter dragover dragleave', '#upload_area', function(e) {
        e.preventDefault();
        uploadMod.doms.uploadErr.html('');
        
        switch (e.type) {
            case 'click':
                $('#upload_input').val(null);
                $('#upload_input').click();
                break;
            case 'drop':
                uploadMod.doms.uploadArea.removeClass('active');
                $('#upload_input').val(null);
                uploadMod.methods.fileUpload();
                break;
            case 'dragenter':
            case 'dragover':
                uploadMod.doms.uploadArea.addClass('active');
                break;
            case 'dragleave':
                uploadMod.doms.uploadArea.removeClass('active');
                break;
        }
    })

    ドラッグしてハイライトに入り、リカバリから遠ざかることができます.$('#upload_input')は、キャッシュされた変数を使用できないことに注意してください.二次クリックアップロードが無効になり、クリックをトリガーしてファイルウィンドウを開くことができません.また、この時点で正しいファイルをドラッグしてアップロードすると、2回のファイルアップロードがトリガーされます.アップロードインタフェースを2回送信します.興味のある方は自分でキャッシュを使ってみてください.
    ケースの再現:
  • 偽の内容が空のapkファイルをクリックすると、ファイルサイズが間違っていることがヒントになります.
  • このとき、2回目のクリックではinputのクリックイベントをトリガーできません.何度も繰り返しても無効です.
  • このとき、ドラッグアップロードにより正常に実行できるが、2回のアップロード処理がトリガーされ、2回のファイルが解析され、2回のアップロードインタフェース要求が送信される.

  • 3.アップロードする前にAPKファイル情報を知らない場合、アップロード操作を実行して解析したファイル情報をパラメータとしてアップロードインタフェースに入れる必要がある
    以前に作成したアップロードは、アップロード前にアップロード時にコミットする必要がある追加のパラメータ値を知っていました.
    $('#upload_input').fileupload({
        url: 'http://localhost:80/jq-drag-upload-apk-parse/upload.php',
        dataType: 'json',
        formData: params, // params   js   ,        
        multi: false,
        //   ....
    })

    しかし、現在では、アップロード前にパラメータ値が分からないため、アップロード操作を実行し、アップロードファイル情報を取得し、アップロードファイルの情報を解析し、解析情報をパラメータ値としてアップロード要求に格納する必要がある.どうすればいいですか.長い間研究して、やっと見つけました.
    $('#upload_input').fileupload({
        url: 'http://localhost:80/jq-drag-upload-apk-parse/upload.php',
        dataType: 'json',
        formData: params, // params   js   ,        
        multi: false,
        add: function (e, data) {
            //            
            //    APK            UI    
            
            $(e.target).fileupload(
                'option',
                'formData',
                formAppInfo // APK       
            );
            data.submit();
        },
        //   ....
    })

    4.アップロード中にアップロードをキャンセルする
    これは比較的簡単です.アップロードコール中のdata.abort()で実現できます.処理する必要があるのは,add()メソッドではまず外層にdataをキャッシュしてから呼び出しを容易にする必要がある.
    $('#upload_input').fileupload({
        url: 'http://localhost:80/jq-drag-upload-apk-parse/upload.php',
        dataType: 'json',
        formData: params, // params   js   ,        
        multi: false,
        add: function (e, data) {
            //            
            //    APK            UI    
            
            //     ,       
            uploadMod.uploadXHR = data;
            
            $(e.target).fileupload(
                'option',
                'formData',
                formAppInfo // APK       
            );
            data.submit();
        },
        fail: function(e, data) {
            if (data.errorThrown == 'abort') {
                uploadMod.doms.uploadErr.html('     ,     ');
            } else {
                uploadMod.doms.uploadErr.html('    ,     ');
            }
        },
        //   ....
    })
    $('body').on('click', '#upload_cancel', function () {
        uploadMod.uploadXHR.abort();
    })

    5.ファイルアップロードの主なコード
    fileCheck: function(e, data) {
        //            
        var acceptFileTypes = uploadMod.doms.uploadInput.attr('accept');
        var supportFileTypes = ['apk']; //   name       ,      type   
        var maxSize = uploadMod.doms.uploadInput.data('size') * 1024 * 1024; //   mb,     b
        var fileTypeFlag = data.originalFiles.every(function(item) {
            if (item.type) {
               return acceptFileTypes.indexOf(item.type) > -1;
            } else {
               var splits = (item.name || file).split('.');
               var fileType = splits[splits.length - 1];
               return supportFileTypes.indexOf(fileType) > -1;
            }
        });
        if (!fileTypeFlag) {
            uploadMod.doms.uploadErr.html('    APK   ');
            return false;
        }
        var fileSizeFlag = data.originalFiles.every(function(item) {
            return item.size > 0 && item.size <= maxSize;
        });
        if (!fileSizeFlag) {
            data = {};
            uploadMod.doms.uploadErr.html('       ');
            return false;
        }
        
        uploadMod.doms.progressWrap.show();
        var $appParse = uploadMod.doms.progressWrap.find('.app-parse'),
            $progressCon = uploadMod.doms.progressWrap.find('.con');
        $appParse.show();
        $progressCon.hide();
    
        // apk     
        var parser = new AppInfoParser(data.files[0]);
        parser.parse().then(function(result) {
            uploadMod.doms.uploadErr.html('');
            var appInfo = result.application || {};
            var formAppInfo = {
                name: appInfo.label ? (Array.isArray(appInfo.label) ? appInfo.label[0] : appInfo.label) : '',
                package: result.package,
                version: result.versionName,
                version_code: result.versionCode
            };
    
            //       
            $appParse.hide();
            $progressCon.show();
            if (result.icon) {
                uploadMod.doms.progressWrap.find('.icon-app').css('background-image', 'url("' + result.icon + '")');
            }
            uploadMod.doms.progressWrap.find('.name').html(formAppInfo.name);
            uploadMod.doms.progressWrap.find('.package').html(formAppInfo.package);
            uploadMod.doms.progressWrap.find('.version').html(formAppInfo.version);
            uploadMod.doms.progressWrap.find('.version-code').html(formAppInfo.version_code);
            uploadMod.doms.progressWrap.find('.progress').css('width', 0);
            uploadMod.doms.progressWrap.find('.num').html(0);
            uploadMod.doms.progressWrap.find('.size').html(0);
    
            //         
            uploadMod.uploadXHR = data;
            $(e.target).fileupload(
                'option',
                'formData',
                formAppInfo
            );
            data.submit();
        }).catch(function (err) {
            uploadMod.doms.progressWrap.hide();
            uploadMod.doms.uploadErr.html('      ,     ');
            data.abort();
        });
        
        // console.error()     
        consoleError = window.console.error;
        window.console.error = function () {
            consoleError && consoleError.apply(window, arguments);
            for (var info in arguments) {
                if (arguments[info] == 'File format is not recognized.') {
                    $('#app_parse').html('

    APK , , , ,

    '); setTimeout(function () { history.go(0); }, 3000); return false; } } }; }, fileUpload: function(el) { $('#upload_input').fileupload({ url: 'http://localhost:80/jq-drag-upload-apk-parse/upload.php', dataType: 'json', multi: false, add: uploadMod.methods.fileCheck, paste: function () { return false; }, done: function(e, data) { // var result = data.result; if (result && result.flag && result.data) { uploadMod.doms.uploadErr.html(result.msg || ' '); uploadMod.data.selectedAPK = result.data; uploadMod.methods.renderHistory(result.data); } else { uploadMod.doms.progressWrap.hide(); uploadMod.doms.uploadErr.html(result.msg || ' '); } }, fail: function(e, data) { if (data.errorThrown == 'abort') { uploadMod.doms.uploadErr.html(' , '); } else { uploadMod.doms.uploadErr.html(' , '); } }, progressall: function(e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); uploadMod.doms.progressWrap.find('.progress').css('width', progress + '%'); uploadMod.doms.progressWrap.find('.num').html(progress); uploadMod.doms.progressWrap.find('.size').html(bytesToSize(data.bitrate)); function bytesToSize(bit) { if (bit === 0) return '0 B'; var bytes = bit / 8; var k = 1024, sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes) / Math.log(k)); return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]; } } }) },

    php環境の簡単な構築
  • xampp統合環境パッケージをダウンロードして
  • をインストール
  • demoプロジェクトの解凍コピーがインストールディレクトリのhtdocsにコピーされたディレクトリの下で、私のディレクトリはC:\xampp\htdocs\jq-drag-upload-apk-parse
  • です.
  • phpアップロードに制限があるため、ファイルC:\xampp\php\php.iniを変更する必要があります.変更する必要がある点:
  • max_execution_time = 0、デフォルト30秒、0は無制限
  • post_max_size = 500M、デフォルト2 M
  • upload_max_filesize = 100M、デフォルト8 M
  • ps:PHPアップロードサイズ制限
  • 参照
  • 最後にインストールディレクトリの下(C:\xampp)のxamppをクリックする.control.exeはインタフェースを開き、オープンインタフェースでApache対応Actionsを
  • 開く.
  • ブラウザウィンドウ入力http://localhost/jq-drag-upload-apk-parse/index.html
  • demo効果
  • を完全に表示
  • ソースアドレス