很多項(xiàng)目都有上傳圖片的功能朴恳,有的保存在自己的服務(wù)器中挥唠,有的使用第三方存儲(chǔ)服務(wù)
這里我們使用七牛提供的對(duì)象存儲(chǔ)服務(wù)
Android開(kāi)發(fā)上傳圖片到七牛的步驟
1. 集成七牛SDK
compile 'com.qiniu:qiniu-android-sdk:7.3.+'
2. 獲得上傳憑證token用于上傳圖片到七牛
這一步?jīng)]啥好說(shuō)的日杈,就是服務(wù)端會(huì)給你一個(gè)接口七冲,你使用該接口獲取token即可
3. 然后調(diào)用七牛的API上傳圖片
Configuration config = new Configuration.Builder()
.chunkSize(512 * 1024) // 分片上傳時(shí)亲配,每片的大小蔓涧。 默認(rèn)256K
.putThreshhold(1024 * 1024) // 啟用分片上傳閥值。默認(rèn)512K
.connectTimeout(10) // 鏈接超時(shí)上渴。默認(rèn)10秒
.useHttps(true) // 是否使用https上傳域名
.responseTimeout(60) // 服務(wù)器響應(yīng)超時(shí)岸梨。默認(rèn)60秒
//.recorder(recorder) // recorder分片上傳時(shí),已上傳片記錄器稠氮。默認(rèn)null
//.recorder(recorder, keyGen) // keyGen 分片上傳時(shí)曹阔,生成標(biāo)識(shí)符,用于片記錄器區(qū)分是那個(gè)文件的上傳記錄
//.zone(FixedZone.zone0) // 設(shè)置區(qū)域括袒,指定不同區(qū)域的上傳域名次兆、備用域名、備用IP锹锰。
.build();
// 重用uploadManager一般地芥炭,只需要?jiǎng)?chuàng)建一個(gè)uploadManager對(duì)象
UploadManager uploadManager = new UploadManager(config);
//data = <File對(duì)象、或 文件路徑恃慧、或 字節(jié)數(shù)組>
//String key = <指定七牛服務(wù)上的文件名园蝠,或 null>;
//String token = <從服務(wù)端獲取>;
uploadManager.put(data, key, token,
new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject res) {
//res包含hash、key等信息痢士,具體字段取決于上傳策略的設(shè)置
if(info.isOK()) {
Log.i("qiniu", "Upload Success");
} else {
Log.i("qiniu", "Upload Fail");
//如果失敗彪薛,這里可以把info信息上報(bào)自己的服務(wù)器茂装,便于后面分析上傳錯(cuò)誤原因
}
Log.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);
}
}, null);
注意:上傳圖片的時(shí)候報(bào)錯(cuò)401 bad token
{ver:7.3.10,ResponseInfo:1514100119681772,status:401, reqId:WgYAAGJX5-KaKgMV, xlog:body:1;UP:2/401, xvia:vdn-fjfz-tel-1-2, host:upload-z2.qiniup.com, path:/, ip:27.155.94.248, port:443, duration:119 s, time:1514100744, sent:28058,error:bad token},
{"error":"bad token"}
這里我檢查了很多遍,也和服務(wù)端再三確認(rèn)token是沒(méi)有錯(cuò)誤的善延,但是為啥會(huì)報(bào)401 bad token
然后ios端的告訴我少态,要對(duì)token字符串進(jìn)行處理,去掉token中的換行符和空格符
String a = qiNiuToken.replace("\\s", "");
String token = a.replace("\n", "");
處理之后再次執(zhí)行易遣,Upload Success成功了彼妻!
這里還是有疑問(wèn)為什么明明Log打印出來(lái)的token字符串根本沒(méi)看到換行符和空格符啊。豆茫。侨歉。。揩魂。
七牛上傳多張圖片的問(wèn)題
問(wèn)題一:怎么解決多圖同時(shí)上傳全部成功監(jiān)聽(tīng)
假設(shè)場(chǎng)景:
現(xiàn)在有一個(gè)新增商品頁(yè)面幽邓,該頁(yè)面需要先上傳產(chǎn)品的5張細(xì)節(jié)圖,拿到5張圖片的url火脉,才能提交新增商品牵舵。
問(wèn)題:
必須要監(jiān)聽(tīng)所有圖片上傳成功,才能執(zhí)行新增商品忘分,但問(wèn)題是七牛的對(duì)象上傳接口默認(rèn)一次只能傳一個(gè)棋枕。
總不可能同步的辦法去一張張上傳圖片,一張傳成功再傳下一張妒峦。這樣當(dāng)圖片很多的時(shí)候很沒(méi)效率浪費(fèi)時(shí)間。
思路:
七牛有提供了上傳進(jìn)度回調(diào)的API兵睛,當(dāng)進(jìn)度percent等于1.0說(shuō)明上傳完成
一張圖片完成肯骇,任務(wù)完成計(jì)數(shù)+1,當(dāng)計(jì)數(shù)等于圖片的數(shù)量時(shí)祖很,說(shuō)明全圖圖片上傳完成笛丙,執(zhí)行新增商品操作
uploadManager.put(data, key, token,handler,
new UploadOptions(null, null, false,
new UpProgressHandler(){
public void progress(String key, double percent){
Log.i("qiniu", key + ": " + percent);//上傳進(jìn)度
}
}, null));
做法如下:
將所有圖片保存在一個(gè)容器中,foreach循環(huán)執(zhí)行上傳圖片的操作
聲明一個(gè)變量來(lái)統(tǒng)計(jì)圖片上傳完成的張數(shù)
private int uploadTaskCount;//七牛上傳圖片完成計(jì)數(shù)
Log.i("qiniu", key + ": " + percent);
if (percent == 1.0)//上傳進(jìn)度等于1.0說(shuō)明上傳完成,通知 完成任務(wù)+1
{
Message message = Message.obtain();
message.what = QI_NIU_UPLOAD_OK;
handler.sendMessage(message);
}
Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case QI_NIU_UPLOAD_OK://七牛上傳圖片完成計(jì)數(shù)
uploadTaskCount++;
Log.e("uploadTaskCount", uploadTaskCount + "");
if (uploadTaskCount == list.size())//容器中圖片全部上傳完成
{
//新增商品
}
break;
}
}
};
問(wèn)題二:有序圖片上傳假颇,返回的URL無(wú)序
假設(shè)場(chǎng)景:
現(xiàn)在有一個(gè)新增商品頁(yè)面胚鸯,該頁(yè)面需要先上傳產(chǎn)品的1張主圖和2張細(xì)節(jié)圖,拿到3張圖片的url保存到url容器中上傳服務(wù)端笨鸡,但是保存url的容器的要求姜钳,順序依次為主圖,細(xì)節(jié)圖形耗,細(xì)節(jié)圖哥桥。
問(wèn)題:
在問(wèn)題一中已經(jīng)可以解決多圖同時(shí)上傳的問(wèn)題,但是 返回的url是無(wú)序的
例如:
圖片文件容器中有a.jpg(10M)激涤,b.jpg(0.5M)拟糕,c.jpg(2M)這三張圖片,a為主圖,bc為細(xì)節(jié)圖送滞。同時(shí)上傳侠草,可能會(huì)出現(xiàn)b.jpg先傳完添加url到url容器中,然后c.jpg傳完添加url到容器中犁嗅,最后才添加a.jpg的url到容器中边涕。這與服務(wù)端要求的url順序,是不符合的
思路
七牛上傳的API中可以指定上傳的圖片在七牛服務(wù)上的文件名
String key = <指定七牛服務(wù)上的文件名愧哟,或 null>;
ata = <File對(duì)象奥吩、或 文件路徑、或 字節(jié)數(shù)組>
String key = <指定七牛服務(wù)上的文件名蕊梧,或 null>;
String token = <從服務(wù)端SDK獲取>;
uploadManager.put(data, key, token,
new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject res) {
//res包含hash霞赫、key等信息,具體字段取決于上傳策略的設(shè)置
if(info.isOK()) {
Log.i("qiniu", "Upload Success");
} else {
Log.i("qiniu", "Upload Fail");
//如果失敗肥矢,這里可以把info信息上報(bào)自己的服務(wù)器端衰,便于后面分析上傳錯(cuò)誤原因
}
Log.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);
}
}, null)
這樣就可以在上傳的時(shí)候把原來(lái)的圖片名+時(shí)間戳指定該圖片在七牛服務(wù)上的文件名
全部圖片上傳完成后得到保存所有圖片的url容器,利用url中的時(shí)間戳對(duì)保存url的容器從新排序甘改。時(shí)間戳最早的就是主圖旅东,放在容器第一個(gè)元素。