Kii BLOG

以断点续传的方式上传下载文件(1)

(一)概述

Kii Cloud支持以断点续传的方式上传文件,并支持多任务多文件同时上传,断点续传的好处不言而喻,例如上传比较大的文件或者网络速度比较慢时,断点续传就体现了他的优势。本文档将从Kii Cloud如何以断点续传的方式上传文件、恢复暂停的上传任务、手动暂停文件上传、手动终止文件上传等几个方面进行阐述,同时提供示例app代码,后面都将基于该示例app进行说明,下面是代码链接下载地址:

UploadingFiles

 

(二)以断点续传的方式上传文件

由于文件的作用域只能是用户级的,所以在上传文件之前必须要完成用户的登录,本示例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按钮添加新的上传任务,其执行效果如下图所示:

Uploading

 

请注意在输入文件名字的时候,默认从SD卡的根目录寻找文件。值得关注的是相同的同一个文件可以建立多个上传任务,也就是说上传任务的建立不去判断是否属于本地的同一个文件,但是对于相同的文件在Kii Cloud端应该有文件的管理机制,例如重新命名等,这个问题有待于后面关于下载文件方面的文章进行说明。

3、手动暂停上传任务

如果任务的状态处于uploading状态,则点击该任务列表的item,则提示是否暂停上传任务,其执行效果如下图所示:

Suspend

 

4、恢复上传任务

那些被暂停了的或者由于某种原因(例如网络断开)而产生错误的任务,可以通过点击列表的相应item恢复上传,其效果如下图所示:

Resume

 

5、终止和移除任务

长按列表的相应item项,可以手动终止那些正在上传或出错的任务,或者清除那些已经完成的任务(这里的清除只是删除该项列表,并不会删除Kii Cloud端的文件),其效果图如下所示:

Remove

 

 

6、注意的问题

以上就是全部的测试过程,这里有一点值得注意,就是在暂停任务时,会出现短暂的error提示,那是因为暂停任务过程中会调用onTransferCompleted回调函数,在该函数中对异常判断时,如果不是正常的完成,会出现error的处理,但是随后会被暂停回调函数的状态所覆盖,这里知道问题的原因就可以了,本示例app并没有对这一块做特殊的判断处理。另外如果想做上传过程中的断网情况,最好不要通过模拟器去测试,因为从我测试的结果看模拟器并不能及时响应断网事件,但是通过手机终端测试就完全没有这样的问题。

 

(七)总结

从以上分析说明可以看出,Kii Cloud为文件上传提供了简洁和实用的接口,开发者可以很容易的管理上传任务,完全不必关心断点续传的内部机制,只需要调用几个接口就轻松地完成任务,在分析完Kii Cloud的上传文件功能之后,下一篇文章将继续分析Kii Cloud的文件下载功能。

 

 相关文章:

以断点续传的方式上传下载文件(1)

以断点续传的方式上传下载文件(2)

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注