七牛是专注文件存储的第三方服务商,服务较好。自己最近做到服务器存储图片的时候就想到用七牛来做,将图片或者文件存放在七牛,然后自己服务器只存放资源存放在七牛文件的url。
今天主要分享两个内容:凭证的获取,安卓上传文件
在做之前还是先把官方文档好好读几遍比较好
首先说说凭证,七牛对所有上传的资源都需要身份验证,就是通过凭证来验证,验证通
过,那么就可以成功上传文件,不通过,七牛服务器会反馈一个上传失败的原因。
凭证相关概念
凭证一般不由客户端颁发,而是由业务服务器产生,分发给客户端,起到安全的保护机
制。具体可以参考七牛的编程模型
编程模型
构造上传凭证需要先构造出上传策略,上传策略是资源上传时附带的一组配置设定。通
过这组配置信息,七牛云存储可以了解用户上传的需求:它将上传什么资源,上传到哪
个空间,上传结果是回调通知还是使用重定向跳转,是否需要设置反馈信息的内容,以
及授权上传的截止时间等等。
在上传策略里可以指定上传完成后的动作,比如是给web客户端一个请求重定向
returnurl并附带retunbody,还是在客户端上传完后七牛给业务服务器一个回调,在
callbackurl可以指定回掉的url,在callbackbody可以指定回掉给业务服务器的内容。服
务器收到回调后还要给七牛一个回调,回调必须设置为json格式,七牛会直接把这个回
调发给客户端。
构造上传凭证的上传策略
接下来就可以构造上传凭证了,在这儿因为上传凭证是应该在服务器产生的,所以这儿
参考java(服务器)sdk开发文档
java服务器SDK开发指南文档
在文档里详细介绍如何生成token(凭证),其中生成凭证有几个参数必填,第一个
bucket,即自己创建的上传空间,第二个指定上传资源的名字,必须要唯一化,如果这
里指定了key,那么在客户端比如安卓上传时候也要指明同一个key,否则上传失败,当
然如果需要上传多张图片时候,那么最好在生成token的时候不指定key,那么在安卓端
(客户端)上传时候是可以指定key的(即生成token时候不指定key,在安卓端上传时
候可以指定),这时候指定了key,这个key就是上传的文件的名称,最好不要用中文命
名。
生成好token后就可以用token去上传数据了,这里采用的是安卓端,网页也试过,差不
多
安卓上传没什么难度,参考安卓上传SDK开发文档
// 重用 uploadManager。一般地,只需要创建一个 uploadManager 对象
UploadManager uploadManager = new UploadManager();
data =
String key = <指定七牛服务上的文件名,或 null>;
String token = <从服务端SDK获取>;
uploadManager.put(data, key, token,
new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject res) {
// res 包含hash、key等信息,具体字段取决于上传策略的设置。
Log.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);
}
}, null);
其中key指定上传文件的名称,第三个参数为七牛反馈的回调,在jsonobject里面反馈的
数据都是在上传策略里面指定的类型。其他的断点上传,分片上传,上传进度获取在开
发文档都有了。
最后总结一些问题:
在token里指定key,那么上传文件时也要指定相同的key,否则上传失败。如果在token
里可以不指定key,在上传时指定也没事,key即为bucket保存的文件名。
关于七牛包的依赖问题也是比较麻烦,安卓端注意sdk版本依赖问题。可以参考另一篇
博文:七牛关于sdk的依赖包问题
在上传数据失败,各种状态码解决方案请参考:七牛错误状态码解析
关于七牛回调请参考:七牛回调理解
具体 以后有什么使用感悟再更新,有什么问题欢迎指正,谢谢!
给出生成token的代码(java版本)
package test; import com.qiniu.util.Auth; import com.qiniu.util.StringMap; public class TestQiniu { public static void main(String[] args) { String uptoken = getUptoken(); System.out.println(uptoken); } private static String getUptoken() { Auth auth = Auth.create("AK", "SK"); String uptoken = auth .uploadToken( "agriculturetest", null, 3600, new StringMap() .putNotEmpty( "returnBody", "{\"key\": $(key), \"imageAve\": $(imageAve), \"width\": $(imageInfo.width), \"height\": $(imageInfo.height)}")); return uptoken; } }
package com.example.testqiniutoken;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.qiniu.android.http.ResponseInfo;
import com.qiniu.android.storage.UpCompletionHandler;
import com.qiniu.android.storage.UploadManager;
public class MainActivity extends Activity implements OnClickListener {
private Button button;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(this);
}
public byte[] getBytes(InputStream is) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[2048];
int len;
try {
while ((len = is.read(b, 0, 2048)) != -1) {
baos.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
baos.flush();
} catch (IOException e) {
e.printStackTrace();
}
return baos.toByteArray();
}
@Override
public void onClick(View v) {
try {
InputStream is = getResources().getAssets().open(
"146459-105.jpg");
byte[] bytes = getBytes(is);
UploadManager uploadManager = new UploadManager();
//第二个参数就是指定在bucket里面存储文件的名字,唯一性
uploadManager
.put(bytes,
"meinv",
"8EqgYr4A18xyeUzWdDHt6OKTKJ5wW9mttLKiobF_:vMN2oe1OFKTkBHPv0TplIfTBjyw=:eyJzY29wZSI6ImFncmljdWx0dXJldGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjogJChrZXkpLCBcImltYWdlQXZlXCI6ICQoaW1hZ2VBdmUpLCBcIndpZHRoXCI6ICQoaW1hZ2VJbmZvLndpZHRoKSwgXCJoZWlnaHRcIjogJChpbWFnZUluZm8uaGVpZ2h0KX0iLCJkZWFkbGluZSI6MTQ1MjkzMzUxOX0=",
new UpCompletionHandler() {
@Override
public void complete(String key,
ResponseInfo info, JSONObject response) {
Log.e(TAG, key);
Log.e(TAG, info.toString());
Log.e(TAG, "上传是否成功"+info.isOK());
//上传失败的话response是null !!!!!!
if (response!=null) {
Log.e(TAG, response.toString());
}
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}