Kii BLOG
以断点续传的方式上传下载文件(1)
(一)概述
Kii Cloud支持以断点续传的方式上传文件,并支持多任务多文件同时上传,断点续传的好处不言而喻,例如上传比较大的文件或者网络速度比较慢时,断点续传就体现了他的优势。本文档将从Kii Cloud如何以断点续传的方式上传文件、恢复暂停的上传任务、手动暂停文件上传、手动终止文件上传等几个方面进行阐述,同时提供示例app代码,后面都将基于该示例app进行说明,下面是代码链接下载地址:
(二)以断点续传的方式上传文件
由于文件的作用域只能是用户级的,所以在上传文件之前必须要完成用户的登录,本示例app提供了登录和注册接口,读者可以通过该接口进行登录或注册。上传文件需要完成以下几个步骤:
- 创建目标文件。
- 调用
file
方法创建一个KiiFile
实例。 - 传递目标文件的引用给
uploader
方法创建一个KiiUploader
实例。 - 开始上传,本示例代码中通过调用transferAsync方法实现上传。
下面是相关的示例代码:
UploaderObj mUploaderObj = null; KiiFile kfile = null ; KiiUploader uploader = null; File localFile = new File(Environment.getExternalStorageDirectory(), mEditTextFileName.getText().toString()); if (localFile.isFile()) { try { kfile = Kii.fileBucket(BUCKET_NAME).file(); uploader = kfile.uploader(getApplicationContext(), localFile); } catch (Exception e) { Toast.makeText(MainActivity.this, "create uploader failed", Toast.LENGTH_LONG).show(); return; } ... new UploadFileTask().execute(mUploaderObj); } else { Toast.makeText(MainActivity.this, "File does not exist", Toast.LENGTH_LONG).show(); }
其中UploadFileTask用来完成后台文件上传的任务,transferAsync就是在该任务里被调用,其相关代码如下:
private class UploadFileTask extends AsyncTask<UploaderObj, String, String> { private UploaderObj mUploaderObj; @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(UploaderObj... params) { mUploaderObj = params[0]; mUploaderObj.uploader.transferAsync( new KiiRTransferCallback() { public void onStart(KiiRTransfer operator) { mUploaderObj.status = STATUS_UPLOADING; mListAdapter.notifyDataSetChanged(); } public void onProgress(KiiRTransfer operator, long completedInBytes, long totalSizeinBytes) { mUploaderObj.completedInBytes = completedInBytes; mUploaderObj.totalSizeinBytes = totalSizeinBytes; mListAdapter.notifyDataSetChanged(); } public void onTransferCompleted(KiiRTransfer operator, java.lang.Exception e) { if (e == null) { mUploaderObj.status = STATUS_FINISHED; } else { mUploaderObj.status = STATUS_ERROR; } mListAdapter.notifyDataSetChanged(); } } ); return null; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); } }
这里使用了transferAsync的回调函数,包括用来提示上传开始的onStart函数、用来提示当前上传进度的onProgress函数和用来提示上传完毕的onTransferCompleted函数,比较详细的代码请参考示例app的源码。
(三)恢复暂停的上传任务
恢复暂停的上传任务在示例app里分为两种情况,一种是程序启动时恢复所有基于该用户指定fileBucket下处于挂起状态的任务,另外一种就是app执行过程中由用户手动暂停的任务,虽然从应用层面上看分为这两种情况,但实际最终调用的还是上面提到的transferAsync方法,下面分这两种情况分别说明:
1、app启动时的上传任务恢复
- 启动时的上传任务恢复主要完成以下几步工作:
- 获取当前用户下指定的KiiFileBucket实例
- 通过KiiFileBucket获取KiiRTransferManager实例
- 通过KiiRTransferManager的listUploadEntries获取处于挂起状态的KiiUploader实例列表
下面是具体的示例代码:
private void loadUploaders() { boolean isError = false; UploaderObj mUploaderObj = null; mProgress = ProgressDialog.show(MainActivity.this, "", "Loading...", true); // default to an empty adapter mListAdapter.clear(); KiiFileBucket fbucket = KiiUser.getCurrentUser().fileBucket(BUCKET_NAME); KiiRTransferManager manager = fbucket.getTransferManager(); List<KiiUploader> suspended = null; try { suspended = manager.listUploadEntries(getApplicationContext()); } catch (StateStoreAccessException e1){ // Failed to access the local storage. // This is a rare error; you should be able to safely retry. Toast.makeText(MainActivity.this, "Error loading uploaders: " + e1.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); isError = true; } if (isError == false) { for (KiiUploader uploader : suspended) { mUploaderObj = new UploaderObj(); mUploaderObj.uploader = uploader; mListAdapter.add(mUploaderObj); new UploadFileTask().execute(mUploaderObj); } } mProgress.dismiss(); }
从上面的代码中可以看出,在获取到KiiUploader实例之后,还是通过任务UploadFileTask完成后台文件的上传。
2、恢复手动暂停的任务
在示例代码中,如果上传任务处于暂停或错误状态,此时点击该列表item,会提示是否恢复任务,在这种情况直接通过后台任务重新上传该KiiUploader即可,示例代码如下:
void performResume(int position) { final UploaderObj o = MainActivity.this.mListAdapter.getItem(position); Toast.makeText(MainActivity.this, "Resumed uploader", Toast.LENGTH_SHORT).show(); new UploadFileTask().execute(o); }
(四)手动暂停文件上传
如果一个上传任务正在执行,可以通过手动暂停的方式暂停该任务,本示例代码中采用suspendAsync方法暂停任务,并通过回调函数onSuspendCompleted判断暂停返回的结果,示例代码如下:
void performSuspend(int position) { // show a progress dialog to the user mProgress = ProgressDialog.show(MainActivity.this, "", "Suspending object...", true); final UploaderObj o = MainActivity.this.mListAdapter.getItem(position); o.uploader.suspendAsync( new KiiRTransferCallback() { public void onSuspendCompleted(KiiRTransfer operator, java.lang.Exception e) { if (e == null) { Toast.makeText(MainActivity.this, "Suspended uploader", Toast.LENGTH_SHORT).show(); o.status = STATUS_SUSPENDED; } else { Toast.makeText(MainActivity.this, "Error suspending uploader", Toast.LENGTH_SHORT).show(); o.status = STATUS_ERROR; } mProgress.dismiss(); mListAdapter.notifyDataSetChanged(); } }); }
(五)手动终止文件上传
都有哪类上传任务可以终止呢?包括正在上传的任务、已经手动终止或上传过程中出错的任务。上传任务一旦终止,则不能续传,只能重头开始上传,相关示例代码如下:
{ // build the alert AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Would you like to remove this item?") .setCancelable(true) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { // if the user chooses 'yes', public void onClick(DialogInterface dialog, int id) { // perform the delete action on the tapped object MainActivity.this.performDelete(position); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { // if the user chooses 'no' public void onClick(DialogInterface dialog, int id) { // simply dismiss the dialog dialog.cancel(); } }); // show the dialog builder.create().show(); }
(六)示例app的测试方法
1、登录和注册
首先通过用户管理界面完成登录或注册。
2、上传文件
进入上传任务界面之后,如果该用户下指定fileBucket存在未完成的上传任务,则app启动后会自动加载这些上传文件并从上次上传点继续上传,或者通过add按钮添加新的上传任务,其执行效果如下图所示:
请注意在输入文件名字的时候,默认从SD卡的根目录寻找文件。值得关注的是相同的同一个文件可以建立多个上传任务,也就是说上传任务的建立不去判断是否属于本地的同一个文件,但是对于相同的文件在Kii Cloud端应该有文件的管理机制,例如重新命名等,这个问题有待于后面关于下载文件方面的文章进行说明。
3、手动暂停上传任务
如果任务的状态处于uploading状态,则点击该任务列表的item,则提示是否暂停上传任务,其执行效果如下图所示:
4、恢复上传任务
那些被暂停了的或者由于某种原因(例如网络断开)而产生错误的任务,可以通过点击列表的相应item恢复上传,其效果如下图所示:
5、终止和移除任务
长按列表的相应item项,可以手动终止那些正在上传或出错的任务,或者清除那些已经完成的任务(这里的清除只是删除该项列表,并不会删除Kii Cloud端的文件),其效果图如下所示:
6、注意的问题
以上就是全部的测试过程,这里有一点值得注意,就是在暂停任务时,会出现短暂的error提示,那是因为暂停任务过程中会调用onTransferCompleted回调函数,在该函数中对异常判断时,如果不是正常的完成,会出现error的处理,但是随后会被暂停回调函数的状态所覆盖,这里知道问题的原因就可以了,本示例app并没有对这一块做特殊的判断处理。另外如果想做上传过程中的断网情况,最好不要通过模拟器去测试,因为从我测试的结果看模拟器并不能及时响应断网事件,但是通过手机终端测试就完全没有这样的问题。
(七)总结
从以上分析说明可以看出,Kii Cloud为文件上传提供了简洁和实用的接口,开发者可以很容易的管理上传任务,完全不必关心断点续传的内部机制,只需要调用几个接口就轻松地完成任务,在分析完Kii Cloud的上传文件功能之后,下一篇文章将继续分析Kii Cloud的文件下载功能。
相关文章:
以断点续传的方式上传下载文件(1)