本文針對於qiniu的javaSDK使用教程進行編寫並測試,僅測試部分功能。
1,因為最近要用到cdn,正好之前注冊過七牛,所以研究了一下。
2,使用前提:七牛賬戶。
3,七牛的開發者中心提供了非常詳細的api文檔,具體請參考Java SDK使用指南
4,下載相關包qiniu-java-sdk-7、Google Gson 、okhttp (JDK1.7 及以上) 、okio (JDK1.7 及以上)、okhttp-jdk1.6 、okio-jdk1.6(我直接從官網拷過來的鏈接)
正式開始
一,上傳
上傳主要分為兩步:
- 業務服務器頒發 uptoken(上傳授權憑證)給客戶端(終端用戶)
- 客戶端憑借 uptoken 上傳文件到七牛
先介紹獲取token下面的代碼是獲取token的一個方法,通過傳入相關參數即可獲取token。官網上還提供了幾種簡單的方法,根據需要進行選擇,這里我用的是參數最全的一個。
1 /** 2 * 生成上傳token 3 * 4 * @param bucket 5 * 空間名 6 * @param key 7 * key,可為 null 8 * @param expires 9 * 有效時長,單位秒。默認3600s 10 * @param policy 11 * 上傳策略的其它參數,如 new StringMap().put("endUser", 12 * "uid").putNotEmpty("returnBody", "")。 scope通過 13 * bucket、key間接設置,deadline 通過 expires 間接設置 (此處的設置會影響下面的文件上傳時返回的參數) 14 * @param strict 15 * 是否去除非限定的策略字段,默認true 16 * @return 生成的上傳token 17 */ 18 public String uploadToken(String bucket, String key, long expires, StringMap policy, boolean strict) { 19 20 return auth.uploadToken(bucket, key, expires, policy, strict); 21 22 }
下面是上傳文件
這個是原方法
/** * 上傳數據 * * @param data 上傳的數據 byte[]、File、filePath * @param key 上傳數據保存的文件名 * @param token 上傳憑證 * @param params 自定義參數,如 params.put("x:foo", "foo") * @param mime 指定文件mimetype * @param checkCrc 是否驗證crc32 * @return 返回參數JSON類型 * @throws QiniuException */ public Response put(XXXX data, String key, String token, StringMap params, String mime, boolean checkCrc) throws QiniuException
使用的話先實例化UploadManager
UploadManager uploadManager = new UploadManager();
然后調用即可,下面是我封裝的一個簡單的方法
/** * 上傳圖片 * @param file * @param fileName */ private void upload(File file,String fileName) { try { Response res = uploadManager.put(file, fileName, token); // Map m2 = res.jsonToObject(Map.class); // Map<String, Object> m3 = res.jsonToObject(Map.class); Map<String, Object> m4 = res.jsonToObject(HashMap.class); // StringMap m1 = res.jsonToMap(); System.out.println(m4.get("key")); System.out.println(m4.get("hash")); System.out.println(m4.get("width")); System.out.println(m4.get("height")); System.out.println(res); System.out.println(res.bodyString()); } catch (QiniuException e) { Response r = e.response; // 請求失敗時簡單狀態信息 System.out.println(r.toString()); try { // 響應的文本信息 System.out.println(r.bodyString()); } catch (QiniuException e1) { // ignore } } }
運行后返回的參數為
1448699528661.png //key FtAbKp8pY3gIoEIdsgrMdmiVTuUi //hash 500.0 //width 531.0 //height {ResponseInfo:com.qiniu.http.Response@d86cae,status:200, reqId:giUAAOpSzwWM0BoU, xlog:s.ph;s.put.tw;s.put.tr:1;s.put.tw;s.put.tr:2;s.ph;s.put.tw;s.put.tr:2;s.ph;PFDS:2;PFDS:3;PFDS:4;rs16_8.sel/not found;rs15_8.sel/not found;rdb.g/no such key;DBD/404;v4.get/Document not found;rs16_8.ins;qtbl.ins:2;mc.s;RS:2;rs.put:3;rs-upload.putFile:9;FOPAGENT;IMAGE:2;FOPAGENT:3;FOPAGENT;IMAGE:2;FOPAGENT:3;FOPG:4;FOPAGENT;UP:21, xvia:, adress:up.qiniu.com/101.71.89.200:80, duration:0.000000 s, error:null} //res {"key": "1448699528661.png", "hash": "FtAbKp8pY3gIoEIdsgrMdmiVTuUi", "width": 500, "height": 531} //res.bodyString()
這里的返回參數全是由最前面的putPolicy定義的,我是這樣子定義的
private final static StringMap policy = new StringMap().putNotEmpty("returnBody", "{\"key\": $(key), \"hash\": $(etag), \"width\": $(imageInfo.width), \"height\": $(imageInfo.height)}"); //我是僅用於上傳圖片才這樣定義的
這里有個putPolicy詳細介紹
二,文件操作
根據前綴獲取空間文件列表,文件名設置為空的話是全部獲取
/** * 根據前綴獲取文件列表的迭代器 * * @param bucket 空間名 * @param prefix 文件名前綴 * @param limit 每次迭代的長度限制,最大1000,推薦值 100 * @param delimiter 指定目錄分隔符,列出所有公共前綴(模擬列出目錄效果)。缺省值為空字符串 * @return FileInfo迭代器 */ // BucketManager.FileListIterator it = bucketManager.createFileListIterator(bucket, prefix) public void fileList(String prefix) { BucketManager.FileListIterator it = bm.createFileListIterator(bucket, prefix, 100, null); System.out.println(it.toString()); while (it.hasNext()) { FileInfo[] items = it.next(); System.out.println(items.length); for (int i = 0; i < items.length; i++) { System.out.println(items[i].key+"---"+items[i].hash); } } }
抓取資源
這個功能非常好,而且方法很簡單。
//要求url可公網正常訪問,不指定 key 時以文件的 hash 值為 key bucketManager.fetch(url, bucket); //要求url可公網正常訪問 bucketManager.fetch(url, bucket, key);
三,生成私有空間的文件外鏈
私有空間才需要這一步
找到鏈接
我們需要先上
找到這個鏈接,或者去
也能找到,但是比較麻煩,不過第二種可以進行校驗一會我們生成的url是否正確。
開始構造鏈接。
//java默認的getTime()是獲取的毫秒數,我們需要將其轉換成功秒,然后保存時間為5min String time = ""+(new Date().getTime()/1000+5*60); //e指的是過期時間。Unix時間戳 String url = "http://xx.xx.xx.x.clouddn.com/"+fileName+"?e="+time;
對上一步得到的url進行HMAC-SHA1簽名,並對結果做URL安全的Base64編碼:
進行簽名我是參考Java加密技術,進行加密
class HMACSHA1 { private static final String MAC_NAME = "HmacSHA1"; private static final String ENCODING = "UTF-8"; /** * 使用 HMAC-SHA1 簽名方法對對encryptText進行簽名 * @param encryptText 被簽名的字符串 * @param encryptKey 密鑰 * @return * @throws Exception */ public String HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception { byte[] data=encryptKey.getBytes(ENCODING); //根據給定的字節數組構造一個密鑰,第二參數指定一個密鑰算法的名稱 SecretKey secretKey = new SecretKeySpec(data, MAC_NAME); //生成一個指定 Mac 算法 的 Mac 對象 Mac mac = Mac.getInstance(MAC_NAME); //用給定密鑰初始化 Mac 對象 mac.init(secretKey); byte[] text = encryptText.getBytes(ENCODING); //完成 Mac 操作 byte[] ft = mac.doFinal(text); //這里的Base64.Default換成Url_safe return Base64.encodeToString(ft, Base64.URL_SAFE); } }
使用
HMACSHA1 h = new HMACSHA1(); String rk = null; try { //這里的sk為七牛給你的secretKey rk = h.HmacSHA1Encrypt(url, SK); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
將AccessKey與上一步計算得到的結果以“:”連接起來:
//這里的ak為accessKey url = url+"&token="+AK+":"+rk;
這樣就生成了生命周期為5分鍾的鏈接。
三,結束
折騰了幾個小時測試了部分方法,其實官網給的方法已經非常全面的,我也沒有測試全面,只是簡單的幾個例程。
