七牛云存儲使用中一些常見問題的解決經(jīng)驗

599錯誤處理
如果在與七牛的交互中出現(xiàn)http狀態(tài)碼為599的錯誤,一句話,不要猶豫,直接聯(lián)系七牛技術(shù)支持。七牛的文檔也在很多地方提到這個錯誤,都是指導(dǎo)大家去聯(lián)系技術(shù)支持的。筆者是在分塊上傳后的mkfile調(diào)用時出現(xiàn)的,聯(lián)系技術(shù)支持后,說是調(diào)整了一下,讓我重試。后來就好了…
分塊上傳無法從回調(diào)中獲得文件的原始名
簡單上傳采用的是multipart/form-data方式上傳,七牛服務(wù)端能夠從請求中獲得文件的原始名,并支持使用魔法變量$(fname)回調(diào)業(yè)務(wù)服務(wù)器。不過當(dāng)使用分片上傳的時候情況有所不同。分片上傳需要在最后調(diào)用mkfile,來將分片拼接起來。但是,mkfile接口支持普通的請求,并沒有附帶文件名,所以七牛也就無法獲得文件名,此時從$(fname)中是取不到文件名的。這個問題我也向七牛技術(shù)支持提交了問題,得到的結(jié)果是使用自定義變量mkfile支持將自定義變量放在url中,回調(diào)的時候自定義變量可以傳遞給業(yè)務(wù)服務(wù)器。
慎用圖片預(yù)處理
七牛云支持很多對文件的預(yù)處理,其中最常用的應(yīng)該就是圖片預(yù)處理了,可以對圖片的大小做變換等。七牛推薦使用GET的方式直接指定圖片處理結(jié)果的url,像這樣:
http://qiniuphotos.qiniudn.com/gogopher.jpg?imageView2/1/w/200/h/200
處理后的圖片會自動緩存,用戶不用關(guān)心,只要每次訪問都用這個url就行了。然而,筆者在開始的時候,為了保持與其他文件形式統(tǒng)一的處理方法,對圖片使用了預(yù)處理(因為視頻什么的只能預(yù)處理),即在token中指定了預(yù)處理。此時問題出現(xiàn)了,從后臺的日志看到,圖片的預(yù)處理通知回調(diào)竟然比正常的上傳成功回調(diào)還要快!這就導(dǎo)致預(yù)處理結(jié)果到來之前,我的業(yè)務(wù)服務(wù)器的數(shù)據(jù)庫中還沒有這個圖片,無法保存預(yù)處理結(jié)果了。所以推薦還是使用url直接處理,對圖片要慎用預(yù)處理
視頻文件無法快進播放
通常用戶在觀看視頻的時候都會根據(jù)自己的喜好,快速將視頻定位到指定的時間播放。實現(xiàn)這個功能,需要視頻本身有關(guān)鍵幀信息、服務(wù)端需要支持關(guān)鍵幀播放請求。
但是筆者發(fā)現(xiàn),在使用七牛云轉(zhuǎn)化后的視頻,這樣做是無效的。于是咨詢技術(shù)支持,得到的答案是:轉(zhuǎn)化的文件是具有關(guān)鍵幀的,但七牛使用CDN加速,所以關(guān)鍵幀請求需要CDN的支持,如果想要用這個功能的話,需要單獨聯(lián)系銷售或技術(shù)支持在CDN上配置,而且時間比較長。筆者聯(lián)系了銷售和技術(shù)支持,說是幫我配置,但到現(xiàn)在還沒有搞定,因為最近這個也不是特別重要,所以也沒有跟下去。
Callback校驗
這是可選的一個步驟。由于七牛云會在上傳完成之后回調(diào)業(yè)務(wù)服務(wù)器,所以理論上說業(yè)務(wù)服務(wù)器需要校驗這個回調(diào)的合理性。原理在七牛的文檔中有,需要用到HMAC-SHA1簽名函數(shù)。但是七牛的sdk中沒有提供直接的方式來做校驗,在研讀文檔、多次失敗和查看sdk源碼后,筆者終于校驗成功了。關(guān)鍵的分歧在于,文檔中的這句話:
獲取明文:data = Request.URL.Path +”\n” +Request.Body
這里的Request.URL.Path是否包含Querystring?答案是包含的!下面是筆者C#服務(wù)端的校驗代碼,使用的是ASP.NET Web Api:
- byte[] key = System.Text.Encoding.UTF8.GetBytes(Qiniu.Conf.Config.SECRET_KEY);
- using (HMACSHA1 hmac = new HMACSHA1(key))
- {
- var t = filterContext.Request.Content.ReadAsStringAsync();
- t.Wait();
- string rawbody = t.Result;
- log.DebugFormat("request's rawbody : {0}", rawbody);
- string text = filterContext.Request.RequestUri.PathAndQuery + "\n" + rawbody;
- log.DebugFormat("PathAndQuery + \\n + rawbody : {0}", text);
- byte[] digest = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(text));
- string computed = Qiniu.Util.Base64URLSafe.Encode(digest);
- log.DebugFormat("Computed hash after base64 : {0}", computed);
- IEnumerable<string> auths;
- if (filterContext.Request.Headers.TryGetValues("Authorization", out auths) && auths.Count() == 1)
- {
- string auth = auths.First();
- log.DebugFormat("Authorization in header : {0}", auth);
- if (auth.StartsWith("QBox "))
- {
- var arr = auth.Substring(5).Split(':');
- if (arr.Length == 2)
- {
- if (arr[1] != computed)
- {
- log.ErrorFormat("Authorization failed. Since auth from header {0} not equals computed {1}", arr[1], computed);
- }
- else
- {
- log.Debug("Authorization success.");
- //only pass can be return
- return;
- }
- }
- else
- {
- log.Error("Callback Authorization's format is invalid, can not find two part after split by ':'.");
- }
- }
- else
- {
- log.Error("Callback Authorization's format is invalid, missing leading 'QBox '.");
- }
- }
- else
- {
- log.Error("The request from qiniu callback is missing 'Authorization'");
- }
- filterContext.Response = filterContext.Request.CreateResponse(System.Net.HttpStatusCode.Forbidden);
- }
如下幾個注意點:
明文應(yīng)當(dāng)是請求的path+querystring部分和rawbody
對于.NET而言,明文和key都需要用UTF-8編碼變換成字節(jié)才能進行簽名。而php中的hash_hmac函數(shù)完全不用這么復(fù)雜…
簽名的結(jié)果再用base64的url安全的方式編碼,再與請求的http頭部的Authorization比較
建議官方在文檔中加入一些相對底層一些的編程語言的實現(xiàn),php太高端了…
js-sdk實現(xiàn)略顯粗糙
在使用過程中,我發(fā)現(xiàn)官方的js-sdk有幾個我覺得不好的地方:
不能為每個文件獲取UpToken
試想,在文件上傳過程中有獲取UpToken是必須的,而且UpToken又需要包含預(yù)處理指令,不同的文件顯然需要不同的UpToken,而在js-sdk的實現(xiàn)中,只在初始化這個上傳組件對象的時候請求一次上傳憑證,后面所有的上傳都需要使用這個預(yù)先得到的UpToken:
- uploader.bind('Init', function(up, params) {
- getUpToken();
- });
只能實現(xiàn)分片上傳,無法斷點續(xù)傳
js-sdk的實現(xiàn)在分片上傳的實現(xiàn)上,是很簡單的,不僅沒有使用分片,而是分塊(一塊4m,調(diào)用mkblk),而且沒有實現(xiàn)持久化ctx,或者類似的回調(diào)或接口。4m分塊這個問題還可以不追究,沒有實現(xiàn)持久化ctx就說不過去了,不持久化怎么實現(xiàn)斷點續(xù)傳撒?!就算不實現(xiàn),也應(yīng)該給出回調(diào)的入口,讓調(diào)用者來實現(xiàn)持久化,而我實在無法找到這個’空子’可鉆,只能直接在源碼上改動了。
沒有復(fù)用流行類庫的東西
這個其實算不上問題,因為作為一個不依賴jquery的sdk,當(dāng)然不能使用jquery現(xiàn)成的東西,比如ajax。不依賴jquery就算了,依賴plupload是幾個意思嘛,還依賴全局對象…于是最后,我干脆自己將sdk改成了Backbone的類,將不要的東西統(tǒng)統(tǒng)去掉,使用jquery和underscore簡化代碼了…
相關(guān)文章
詳解利用七牛云存儲簡單托管靜態(tài)網(wǎng)站的方法
這篇文章主要介紹了利用七牛云存儲簡單托管靜態(tài)網(wǎng)站的方法,對于小容量和小流量的靜態(tài)站點來說使用七牛搭建非常便利,需要的朋友可以參考下2016-01-16- 這篇文章主要介紹了使用七牛云存儲的鏡像功能和免費流量來加速網(wǎng)站的方法,但是同時也要注意百度的SEO相關(guān)問題是否與鏡像的使用相關(guān),需要的朋友可以參考下2016-01-03
七牛云儲存創(chuàng)始人分享七牛的創(chuàng)立故事與對Go語言的應(yīng)用
這篇文章主要介紹了七牛云儲存創(chuàng)始人分享七牛的創(chuàng)立故事與對Go語言的應(yīng)用,七牛選用Go語言這門新興的編程語言進行創(chuàng)業(yè)著實吸引了不少目光,需要的朋友可以參考下2015-12-28七牛云存儲使用Go語言架設(shè)網(wǎng)站的經(jīng)驗分享
這篇文章主要介紹了七牛云存儲使用Go語言架設(shè)網(wǎng)站的經(jīng)驗分享,七牛是國內(nèi)大范圍采用Go語言進行網(wǎng)站開發(fā)的代表型案例,需要的朋友可以參考下2015-12-28- 這篇文章主要介紹了集群技術(shù)在七牛云存儲中的應(yīng)用案例分享,作為以云為基礎(chǔ)的七牛云存儲,其在集群技術(shù)方面的利用自然引人關(guān)注,需要的朋友可以參考下2015-12-27
七牛鏡像存儲 WordPress 插件(一鍵實現(xiàn) WordPress 博客靜態(tài)文件 CDN加
對于很多 WordPress 站點來說,有了這個功能,就無需將原來的圖片上傳到七牛的服務(wù)器上,只需在 WordPress 站點做些簡單的修改,就可以使用七牛的 CDN 服務(wù)了,真正顯示一2014-11-29- 今天我要為大家推薦的是最近國內(nèi)比較火的一個面向創(chuàng)業(yè)者的第三方服務(wù):七牛云存儲2013-11-29