第三方存储:为了减少开发成本,减轻服务器压力,降低分布式开发难度,提高数据安全性,在开发过程中我们常常可以把一些数据存储到第三方云服务中。
七牛云: 中国企业级公有云服务商,提供对象存储,融合CDN加速,直播云等服务。
优势:对于10GB以下数据免费,提高详尽的开发者文档,地址:https://developer.qiniu.com/
实现思路:1.安卓客户端向服务器发送请求,表明自己要进行第三方存储,获取token
2.服务器通过服务器端SDK与第三方交互,表明目的,获取第三方返回的token
3.服务器将token返回给安卓端,安卓端获取token
4.安卓客户端通过客户端SDK将需要上传的图片和token一起发送到第三方云
5.客户端告知服务器端第三方存储过程结束
1.客户端向服务器端发送请求获取数据
2.服务器端通过SDK与第三方交互获得图片的URL,返回给客户端
3.安卓客户端通过URL获取图片
代码示例:
添加sdk依赖:
public class MainActivity extends AppCompatActivity {
private ProgressDialog progressDlg;
private Intent intent;
private final int NONE=0,LOCAL_PICTURE=1,UPLOAD_TAKE_PICTURE=2,SAVE_THEME_IMAGE=3;
private String takePictureUrl,upToken, imageFileName;
ImageView photo;
TextView select_local_picture;
TextView download_picture;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
photo=(ImageView)findViewById(R.id.imageView); //上传和下载的图片位置
select_local_picture=(TextView)findViewById(R.id.textView); //上传图片的按钮
download_picture=(TextView)findViewById(R.id.textView2);
//点击选择本地图片
select_local_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*");
startActivityForResult(intent,LOCAL_PICTURE);
}
});
//点击下载图片
download_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap map = new HashMap();
map.put("请求类型", "请求下载图片");
requestFragment.httpRequest(map, CommonUrl.getPhoto); //服务器请求
}
});
}
//选择图片完成后
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==NONE)
return;
//耗时操作传到handler里去处理
if(resultCode== Activity.RESULT_OK){
this.intent=data;
handler.sendEmptyMessage(LOCAL_PICTURE);
}
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case LOCAL_PICTURE:
//处理本地选择的图片
Uri uri=intent.getData();
String photo_local_file_path="图片地址"; //使用uri获取图片地址略
if (!(photo_local_file_path.toString().toLowerCase().endsWith("jpg")||photo_local_file_path.toString().toLowerCase().endsWith("png")
||photo_local_file_path.toString().toLowerCase().endsWith("jpeg")||photo_local_file_path.toString().toLowerCase().endsWith("gif"))) {
Toast.makeText(MainActivity.this, "不支持此格式的上传", Toast.LENGTH_LONG).show();
break;
}
//简单压缩图片
Bitmap bitmap2=PhotoUtil.getInstance().trasformToZoomPhotoAndLessMemory(photo_local_file_path);
Drawable addPicture =new BitmapDrawable(getResources(), bitmap2);
takePictureUrl=photo_local_file_path;
photo.setImageDrawable(addPicture);
{
//imageFileName为存储在服务器端的图片名
imageFileName = "username" + "/" + takePictureUrl.hashCode() + new Random(System.nanoTime()).toString();
HashMap map = new HashMap();
map.put("请求类型", "请求获得token");
map.put("image", imageFileName);
Log.d("选择了本地照片", "正在请求服务器端获取token");
requestFragment.httpRequest(map,Url.getToken);
}
break;
case UPLOAD_TAKE_PICTURE: //获取token之后
{
//使用SDK传输到七牛云
UploadManager uploadmgr = new UploadManager();
File data = new File(takePictureUrl);
String key = imageFileName;
String token = upToken;
progressDlg = ProgressDialog.show(MainActivity.this, "上传图片", "正在上传图片", true, true, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
//取消了上传
}
});
progressDlg.setMax(101);
uploadmgr.put(data, key, token, new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
//完成,发信息给业务服务器
Log.d("to第三方结果",response.toString());
new Thread() {
public void run() {
Map<String, Object> map = new HashMap<>();
Message msg = handler.obtainMessage();
msg.obj = map;
msg.what = SAVE_THEME_IMAGE;
handler.sendMessage(msg);//要上传的图片包装在msg后变成了消息发到handler
}
}.start();
}
}, new UploadOptions(null, null, false,
new UpProgressHandler() {
public void progress(String key, double percent) {
//mProgress.setProgress((int)percent*100);
progressDlg.setProgress((int) percent * 100);
}
}, null));
}
break;
case SAVE_THEME_IMAGE: //传到第三方之后告知服务器
progressDlg.dismiss();
{
HashMap map = new HashMap();
map.put("请求类型","上传到七牛");
map.put("image",imageFileName);
requestFragment.httpRequest(map, "完成传输"); //在服务器保存图片(只保存图片名)
}
progressDlg=ProgressDialog.show(MainActivity.this, "上传图片", "正在保存图片", true, true, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
//上传完图片后取消了保存
}
});
break;
default: //用户身份认证失败
{
break;
}
}
}
};
//服务器端的响应
public void requestFinish(String result, String requestUrl) throws JSONException {
Message message = new Message();
//获取token
if(requestUrl.equals(("获取口令"))){
JSONObject jsonObject=new JSONObject(result);
int code = Integer.valueOf(jsonObject.getString("code"));
if (code == 1) {
JSONArray token = jsonObject.getJSONArray("contents");
upToken = token.getString(0);//成功获取口令
handler.sendEmptyMessage(UPLOAD_TAKE_PICTURE);
return;
}
else{
Toast.makeText(MainActivity.this, "获取口令失败", Toast.LENGTH_LONG).show();
}
}
if (requestUrl.equals("下载图片")) {
JSONObject object = new JSONObject(result);
int code = Integer.valueOf(object.getString("code"));
if (code == 1) {
String url = "从服务器获得图片的url地址";
//使用picasso等图片处理库获取图片
return;
} else {
// Toast.makeText(profileActivity.this, "未知错误", Toast.LENGTH_LONG).show();
return;
}
}
}
}
备注:本文只讨论客户端相关操作,不涉及服务器端的实现
下一节:picasso图片处理实践讲解