在无线网络下,上传较大的文件持续时间长,可能会遇到因为网络条件差、用户切换网络等原因导致上传中途失败,整个文件需要重新上传。为此,Android SDK提供了断点续传上传功能。
使用说明
Android SDK提供了resumableUpload以及sequenceUpload两种方法用于断点续传上传。
(推荐)resumableUpload表示并发上传分片,即同时支持最多5个分片并发上传。
sequenceUpload表示顺序上传分片,即上一个分片上传完成后开始上传下一个分片。
以下示例代码仅提供通过resumableUpload的方法断点续传上传。如果您希望通过断点续传的方式上传多个文件或视频,需创建多个ResumableUploadRequest。
注意事项
使用本文示例前您需要先通过自定义域名、STS等方式新建OSSClient,具体请参见如何初始化Android端OSSClient实例。
对于移动端而言,如果不是大文件(例如小于5 GB的文件),不建议使用断点续传的方式上传。断点续传上传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。对于通过断点续传的方式上传大于5 GB的文件时:
断点续传上传前
通过断点续传上传的方式将文件上传到OSS前,您可以指定断点记录的保存文件夹。断点续传上传仅在本次上传生效。
如果未指定断点记录的保存文件夹,假设某个分片因为网络原因等导致文件上传失败时,将耗用大量的重试时间及流量来重新上传整个大文件。
如果指定了断点记录的保存文件夹,在文件上传失败时,将从断点记录处继续上传未上传完成的部分。
断点续传上传时
断点续传上传仅支持上传本地文件。断点续传上传支持上传回调,使用方法与常见的上传回调类似。具体操作,请参见Callback。
断点续传上传依赖InitMultipartUpload、UploadPart、ListParts、CompleteMultipartUpload、AbortMultipartUpload等接口来实现。如果您需要通过STS鉴权模式来使用断点续传上传,则需要保证您拥有访问以上API接口的权限。
断点续传上传默认已开启每个分片上传时的MD5校验,因此无需在请求中设置
Content-Md5
头部。如果同一任务一直未完成续传,可能会在OSS上积累无用的碎片。此时,您可以为Bucket设置生命周期规则来定时清理碎片。具体操作,请参见生命周期管理。
示例代码
您可以通过同步或者异步方式断点续传上传本地文件到OSS。
同步的方式
以下代码以同步的方式断点续传上传examplefile.txt文件到目标存储空间examplebucket中exampledir目录下的exampleobject.txt文件,并将断点记录文件保存到本地。
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 填写文件完整路径,例如/storage/emulated/0/oss/examplefile.txt。
String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
File recordDir = new File(recordDirectory);
// 确保断点记录的保存文件夹已存在,如果不存在则新建断点记录的保存文件夹。
if (!recordDir.exists()) {
recordDir.mkdirs();
}
// 创建断点续传上传请求,并指定断点记录文件的保存路径,保存路径为断点记录文件的绝对路径。
ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath, recordDirectory);
// 调用OSSAsyncTask cancel()方法时,设置DeleteUploadOnCancelling为false,表示不删除断点记录文件,下次再上传同一个文件时将从断点记录处继续上传。如果不设置此参数,则默认值为true,表示删除断点记录文件,下次再上传同一个文件时则重新上传。
request.setDeleteUploadOnCancelling(false);
// 设置上传回调。
request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
@Override
public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
ResumableUploadResult uploadResult = oss.resumableUpload(request);
对于Android10及之后版本的分区存储,您可以使用文件的Uri上传文件到OSS。
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
String recordDirectory = getApplication().getFilesDir().getAbsolutePath() + "/oss_record/";
File recordDir = new File(recordDirectory);
// 确保断点记录的保存文件夹已存在,如果不存在则新建断点记录的保存文件夹。
if (!recordDir.exists()) {
recordDir.mkdirs();
}
// 创建断点续传上传请求,并指定断点记录文件的保存路径,保存路径为断点记录文件的绝对路径。
// 这里参数"fileUri"需要填入文件的实际Uri值。
ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, fileUri, recordDirectory);
// 调用OSSAsyncTask cancel()方法时,设置DeleteUploadOnCancelling为false,表示不删除断点记录文件,下次再上传同一个文件时将从断点记录处继续上传。如果不设置此参数,则默认值为true,表示删除断点记录文件,下次再上传同一个文件时则重新上传。
request.setDeleteUploadOnCancelling(false);
// 设置上传回调。
request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
@Override
public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
ResumableUploadResult uploadResult = oss.resumableUpload(request);
如果在断点续传上传时无需将断点记录文件保存到本地,示例代码如下:
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 填写文件完整路径,例如/storage/emulated/0/oss/examplefile.txt。
String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
// 创建断点续传上传请求。
ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath);
// 设置上传回调。
request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
@Override
public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
ResumableUploadResult uploadResult = oss.resumableUpload(request);
异步的方式
以下代码以异步的方式断点续传上传examplefile.txt文件到目标存储空间examplebucket中exampledir目录下的exampleobject.txt文件,并将断点记录文件保存到本地。
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 填写文件完整路径,例如/storage/emulated/0/oss/examplefile.txt。
String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
File recordDir = new File(recordDirectory);
// 确保断点记录的保存路径已存在,如果不存在则新建断点记录的保存路径。
if (!recordDir.exists()) {
recordDir.mkdirs();
}
// 创建断点上传请求,并指定断点记录文件的保存路径,保存路径为断点记录文件的绝对路径。
ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath, recordDirectory);
// 调用OSSAsyncTask cancel()方法时,设置DeleteUploadOnCancelling为false,表示不删除断点记录文件,下次再上传同一个文件时将从断点记录处继续上传。如果不设置此参数,则默认值为true,表示删除断点记录文件,下次再上传同一个文件时则重新上传。
request.setDeleteUploadOnCancelling(false);
// 设置上传过程回调。
request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
@Override
public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
@Override
public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
Log.d("resumableUpload", "success!");
}
@Override
public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 异常处理。
}
});
// 等待完成断点上传任务。
resumableTask.waitUntilFinished();
对于Android10及之后版本的分区存储,您可以使用文件的Uri上传文件到OSS。
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
String recordDirectory = getApplication().getFilesDir().getAbsolutePath() + "/oss_record/";
File recordDir = new File(recordDirectory);
// 确保断点记录的保存文件夹已存在,如果不存在则新建断点记录的保存文件夹。
if (!recordDir.exists()) {
recordDir.mkdirs();
}
// 创建断点续传上传请求,并指定断点记录文件的保存路径,保存路径为断点记录文件的绝对路径。
// 这里参数"fileUri"需要填入文件的实际Uri值。
ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, fileUri, recordDirectory);
// 调用OSSAsyncTask cancel()方法时,设置DeleteUploadOnCancelling为false时,表示不删除断点记录文件,下次再上传同一个文件时将从断点记录处继续上传。如果不设置此参数,则默认值为true,表示删除断点记录文件,下次再上传同一个文件时则重新上传。
request.setDeleteUploadOnCancelling(false);
// 设置上传回调。
request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
@Override
public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
@Override
public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
Log.d("resumableUpload", "success!");
}
@Override
public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 异常处理。
}
});
// 等待完成断点上传任务。
resumableTask.waitUntilFinished();
如果在断点续传上传时无需将断点记录文件保存到本地,示例代码如下:
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 填写文件完整路径,例如/storage/emulated/0/oss/examplefile.txt。
String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
// 创建断点上传请求。
ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath);
// 设置上传过程回调。
request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
@Override
public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
// 异步调用断点上传。
OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
@Override
public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
Log.d("resumableUpload", "success!");
}
@Override
public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 异常处理。
}
});
// 等待完成断点上传任务。
resumableTask.waitUntilFinished();
相关文档
关于Bucket设置生命周期规则,请参见生命周期管理。
关于断点续传上传支持上传回调使用方法,请参见Callback。
关于初始化OSSClient,请参见如何初始化Android端OSSClient实例。