七牛 js JDK使用 - 上傳APP

背景介紹

  • 使用JS將APP(包括安卓和IOS)上傳到七牛 (上傳APP因此不考慮數據處理)javascript

  • uptoken使用JAVA後臺獲得html

  • 七牛上傳基於plupload下面不詳述如何使用參見前端

  • 七牛上傳的簡單案例也不詳述,參見官網事例很清楚了。就是參數必定看仔細!java

  • 清除緩存問題ios

  • IOS APP上傳icon和ipa自動生成plistajax

  • 補充:限制選擇文件類型;打開多個選擇文件窗口算法

踩過的坑

uptoken得到失敗

1.使用前端獲取:
本人是個前端,在後臺還沒給出獲取uptoken接口時,我先選擇了使用JS(uptoken_func參數)獲取進行測試,代碼以下:詳細參見json

// uptoken_func: function (file) {    // 在須要獲取uptoken時,該方法會被調用
    /**
     * 上傳憑證算法實現參考
     * 請注意External Resources項中引用的第三方CryptoJS庫
     */
    var genUpToken = function(accessKey, secretKey, putPolicy) {
        //SETP 2
        var put_policy = JSON.stringify(putPolicy);
        //SETP 3
        var encoded = base64encode(utf16to8(put_policy));
        //SETP 4
        var hash = CryptoJS.HmacSHA1(encoded, secretKey);
        var encoded_signed = hash.toString(CryptoJS.enc.Base64);
        //SETP 5
        var upload_token = accessKey + ":" + safe64(encoded_signed) + ":" + encoded;
        console && console.log("upload_token=", upload_token)
        return upload_token;
  // }

費了半天勁,又是引入CryptoJS,又是加入utf16to8等等方法,最後仍是失敗了,生成了一個uptoken我用來上傳文件上傳失敗,就問七牛工單,他說uptoken過期或者錯誤,這就無法搞了也不知道爲何錯,就在沒有頭緒的時候後臺接口好了,得,用後臺接口,結束!(有童鞋用JS獲取了uptoken的能夠來交流)
不過在錯誤中學習到了uptoken的第三個值(用「:」分割的aaaa:aaaa:aaaa)能夠經過base64解碼獲得上傳策略。圖片描述segmentfault

2.使用後臺獲取(我選擇的是java)
導入gson-1.6.jar和qiniu-java-sdk-7.0.0.jar,如下是qiniu的方法!是用uptoken,傳入須要的參數既能夠得到,本人不作後臺開發就不詳述,就是必定注意參數不要傳錯了,咱們搞了很久AK,SK複製錯了,若是提示uptoken錯誤多檢查幾遍參數。到此完成了一個最簡單的上傳。圖片描述api

4M以上大文件上傳失敗

奇葩同樣的大坑啊,原本就是剛剛上手qiniu還沒搞懂的時候還在鬱悶昨天還好好的怎麼過了一晚就上傳失敗了,查詢資料,全不費功夫社區有人踩過了。看第二個評論,簡單說就是設置uptoken參數不能上傳大文件,必須設置uptoken_url才行,做者說的第一個方法我進不去,就沒有糾結。這個是qiniu的bug!

你直接看源碼就知道它在判斷須要分塊的時候,js-sdk內部設置up.setOption的調用getUptoken(),that.tokenInfo在只填寫token的時候,仍是undefined,因此就出問題了。
由於tokenInfo是在走getNewUpToken()設置的,而getNewUpToken是走填了url纔會執行的函數。

覆蓋已有文件

剛剛拿到需求,思索一番,

  • 方案一:生成一個可用覆蓋文件的uptoken;

  • 方案二:qiniuJSjdk經過配置參數能夠覆蓋文件。

查閱API,社區資料,發現方案一能夠行的通,只需後臺uptoken方法時傳入key參數便可覆蓋服務器上面的key文件。
我原覺得key也是後臺給設定的存儲文件名,(這個key並非服務器存儲的最終文件名)後來才發現不是,詳細看scope參數。

指定上傳的目標資源空間 Bucket 和資源鍵 Key(key的長度最大爲750字節)。有兩種格式:
●<bucket>,表示容許用戶上傳文件到指定的 bucket。在這種格式下文件只能新增,若已存在同名資源上傳則會失敗。
●<bucket>:<key>,表示只容許用戶上傳指定 key的文件。在這種格式下文件默認容許修改,若已存在同名資源則會被覆蓋。若是隻但願上傳指定 key 的文件,而且不容許修改,那麼能夠將下面的insertOnly 屬性值設爲 1。

因爲後臺須要key,因此前臺在uptoken_url時傳參,例如:'/appstore/app/qiniuUploadToken?params=a.png'。

關於文件名

前臺有三個參數和文件名有關:

// unique_names: true,              // 默認false,key爲文件名。若開啓該選項,JS-SDK會爲每一個文件自動生成key(文件名)
// save_key: true,                  // 默認false。若在服務端生成uptoken的上傳策略中指定了sava_key,則開啓,SDK在前端將不對key進行任何處理
'Key': function (up, file) {
    // 若想在前端對每一個文件的key進行個性化處理,能夠配置該函數
    // 該配置必需要在unique_names: false,save_key: false時才生效
    var key = file.name;//**錯誤**
   // do something with key here
   return key
   }

重點看第三個參數,當時沒有在乎就這樣寫的,因此認爲給後臺傳的key就是服務器存儲的文件名,其實否則,是我在JS key中設置了var key = file.name。應該須要前端定一個名字,而不是文件原名。

清除緩存問題

看官方文檔給出以下解決方法,生成管理token,清除緩存。
可是客服給出了更好的解決方案

1、URL 問號傳參刷新:
2、在七牛雲存儲上刷新: 一、登陸portal.qiniu.com 二、工具刷新 三、API 接口文檔刷新:
3、只使用fusion cdn加速,且沒有使用七牛存儲

我選擇了最簡單的第一種,URL 問號傳參。(拋出問題:ios app是ipa url問號傳參,仍是plisturl問號傳參,仍是都須要,待測試驗證,以後更新!)

例如,若是 http://7xt44n.com2.z0.glb.qin...
這個圖片資源沒有更新, 能夠在該 URL 後面加上參數的形式來讓 CDN
強制刷新:http://7xt44n.com2.z0.glb.qin...,CDN
拿到這個 URL 後會強制回七牛的存儲中取回最新的資源。

原理: (用戶建立空間爲普通平臺,在這個平臺下 url 是完整緩存的。也就是說。若是你帶了? 1234 這樣的查詢參數在文件 url
後面,就變成了不一樣的 url,因此不會命中 cdn 的緩存。會去原站七牛拉資源,這時候拉取到的資源就變成了覆蓋更新後的資源了。)

IOS APP上傳icon和ipa自動生成plist

原先的ios部署很是不方便,須要上傳icon和ipa獲得地址後修改plist,再上傳plist。因此就想能不能作到自動。
仍是喜歡先查閱資料看看網上有沒有方案,一無所得。
方案以下:(如下代碼感謝導師的支持)

  1. 使用Arttemplate獲得一個模板

  2. 使用blob獲得一個blob數據用於生成file對象

  3. 使用七牛的表單上傳,結合XMLHttpRequest,formData獲得一個表單數據
    詳細代碼:

function plist(icon57Url, icon512Url, ipaUrl, key,plistUrl) {
    var data = {
        icon57Url: icon57Url,
        icon512Url: icon512Url,
        ipaUrl: ipaUrl,
    };
    var html = template('test', data);
    var blob = new Blob([html], {type: "text/plain"});
    //document.getElementById('content').innerHTML = html;
    var Qiniu_UploadUrl = "http://up.qiniu.com";
    var Qiniu_upload = function (f, token) {
        var xhr = new XMLHttpRequest();
        xhr.open('POST', Qiniu_UploadUrl, true);
        var formData, startDate;
        formData = new FormData();
        //if (key !== null && key !== undefined) formData.append('key', key);
        formData.append('token', token);
        formData.append('name', key + '.plist');
        formData.append('chunk', 0);
        formData.append('chunks', 1);
        formData.append('key', key + '.plist');
        formData.append('file', f, key + '.plist');
        var taking;
        xhr.upload.addEventListener("loadstart", function (up, file) {
            /*up.settings.multipart_params = {
             filename : "xucheng.docx"
             };*/
        }, false);
        xhr.upload.addEventListener("progress", function (evt) {
            if (evt.lengthComputable) {
                /*var nowDate = new Date().getTime();
                 taking = nowDate - startDate;
                 var x = (evt.loaded) / 1024;
                 var y = taking / 1000;
                 var uploadSpeed = (x / y);
                 var formatSpeed;
                 if (uploadSpeed > 1024) {
                 formatSpeed = (uploadSpeed / 1024).toFixed(2) + "Mb\/s";
                 } else {
                 formatSpeed = uploadSpeed.toFixed(2) + "Kb\/s";
                 }*/
                //var percentComplete = Math.round(evt.loaded * 100 / evt.total);
                //progressbar.progressbar("value", percentComplete);
                // console && console.log(percentComplete, ",", formatSpeed);
            }
        }, false);

        xhr.onreadystatechange = function (response) {
            if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText != "") {
                var blkRet = JSON.parse(xhr.responseText);
                Compost('/appstore/app/updateOneProperty',{'id':datascope.appid,'ios_url':plistUrl},function () {
                    $('#ios_url').textbox('setText', plistUrl);
                })
                console.log("plist上傳成功")
            } else if (xhr.status != 200 && xhr.responseText) {

            }
        };
        startDate = new Date().getTime();
        $("#progressbar").show();
        xhr.send(formData);
    };
    /*var reader = new window.FileReader();
     reader.readAsDataURL(blob);
     reader.onloadend = function() {
     var base64data = reader.result;
     console.log(base64data);
     }*/
    $.ajax({
        type: "get",
        url: "/appstore/app/qiniuUploadToken?params=" + key + ".plist",
        async: true,
        dataType: "json",
        success: function (data) {
            var token = data.uptoken;
            console.log(token);
            Qiniu_upload(blob, token);
        }
    });
}

到此最重要的一步自動上傳plist完成!,以此共同窗習。

補充

限制選擇文件類型

plupload插件支持,ipa和apk都是zip類型,因此title是Zip files

filters: {
                mime_types: [
                   {title: "Image files", extensions: "png"}, //限定png後綴上傳
                   {title: "Zip files", extensions: "ipa"}, //限定ipa後綴上傳
                   {title: "Zip files", extensions: "apk"}, //限定apk後綴上傳
                ]
            },

打開多個選擇文件窗口

每次實例化option方法時會( browse_button: *// 上傳選擇的點選按鈕,必需)給按鈕綁定一個點擊事件,因此以後會點擊打開屢次選擇文件窗口。
嘗試解決方案(失敗):銷燬option對象,銷燬對象綁定的事件不會刪除
銷燬綁定事件,因爲沒有事件名稱因此沒法刪除
嘗試解決方案(成功):

if (uploader) {uploader.disableBrowse(true);}
相關文章
相關標籤/搜索