在下载OSS大文件(超过5 GB)到本地的过程中,如果出现网络中断、程序异常退出等问题导致文件下载失败,甚至重试多次仍无法完成下载,您需要使用断点续传下载的方式。断点续传下载将需要下载的大文件分成多个较小的分片并发下载,加速下载完成时间。如果下载过程中,某一分片下载失败,再次下载时会从Checkpoint文件记录的断点继续下载,无需重新下载所有分片。下载完成后,所有分片将合并成完整的文件。
前提条件
注意事项
当前仅支持通过SDK的方式实现断点续传下载,断点续传下载过程中有以下注意事项:
本文以华东1(杭州)外网Endpoint为例。如果您希望通过与OSS同地域的其他阿里云产品访问OSS,请使用内网Endpoint。关于OSS支持的Region与Endpoint的对应关系,请参见OSS地域和访问域名。
本文以从环境变量读取访问凭证为例。如何配置访问凭证,请参见配置访问凭证。
本文以OSS域名新建OSSClient为例。如果您希望通过自定义域名、STS等方式新建OSSClient,请参见配置客户端。
要断点续传下载,您必须有
oss:GetObject
权限。具体操作,请参见为RAM用户授权自定义的权限策略。SDK会将下载的状态信息记录在Checkpoint文件中,所以要确保程序对Checkpoint文件有写权限。
请勿修改Checkpoint文件中携带的校验信息。如果Checkpoint文件损坏,则会重新下载所有分片。
如果下载过程中文件的ETag发生变化、Part丢失或被修改,则重新下载文件。
使用阿里云SDK
以下仅列举常见SDK的断点续传下载的代码示例。关于其他SDK的断点续传下载的代码示例,请参见SDK简介。
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
String region = "cn-hangzhou";
// 创建OSSClient实例。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// 请求10个任务并发下载。
DownloadFileRequest downloadFileRequest = new DownloadFileRequest(bucketName, objectName);
// 指定Object下载到本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
downloadFileRequest.setDownloadFile("D:\\localpath\\examplefile.txt");
// 设置分片大小,单位为字节,取值范围为100 KB~5 GB。默认值为100 KB。
downloadFileRequest.setPartSize(1 * 1024 * 1024);
// 设置分片下载的并发数,默认值为1。
downloadFileRequest.setTaskNum(10);
// 开启断点续传下载,默认关闭。
downloadFileRequest.setEnableCheckpoint(true);
// 设置断点记录文件的完整路径,例如D:\\localpath\\examplefile.txt.dcp。
// 只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
//downloadFileRequest.setCheckpointFile("D:\\localpath\\examplefile.txt.dcp");
// 下载文件。
DownloadFileResult downloadRes = ossClient.downloadFile(downloadFileRequest);
// 下载成功时,会返回文件元数据。
ObjectMetadata objectMetadata = downloadRes.getObjectMetadata();
System.out.println(objectMetadata.getETag());
System.out.println(objectMetadata.getLastModified());
System.out.println(objectMetadata.getUserMetadata().get("meta"));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (Throwable ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# 填写Endpoint对应的Region信息,例如cn-hangzhou。注意,v4签名下,必须填写该参数
region = "cn-hangzhou"
# yourBucketName填写存储空间名称。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
# yourObjectName填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
# yourLocalFile填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
oss2.resumable_download(bucket, 'exampledir/exampleobject.txt', 'D:\\localpath\\examplefile.txt')
# 如未使用参数store指定目录,则会在HOME目录下建立.py-oss-upload目录来保存断点信息。
# Python SDK 2.1.0以上版本支持断点续传下载时设置以下可选参数。
# import sys
# # 当无法确定待下载的数据长度时,total_bytes的值为None。
# def percentage(consumed_bytes, total_bytes):
# if total_bytes:
# rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
# print('\r{0}% '.format(rate), end='')
# sys.stdout.flush()
# # 如果使用store指定了目录,则断点信息将保存在指定目录中。如果使用num_threads设置并发下载线程数,请将oss2.defaults.connection_pool_size设置为大于或等于并发下载线程数。默认并发下载线程数为1。
# oss2.resumable_download(bucket, 'exampledir/exampleobject.txt', 'D:\\localpath\\examplefile.txt',
# store=oss2.ResumableDownloadStore(root='/tmp'),
# # 指定当文件长度大于或等于可选参数multipart_threshold(默认值为10 MB)时,则使用断点续传下载。
# multiget_threshold=100*1024,
# # 设置分片大小,单位为字节,取值范围为100 KB~5 GB。默认值为100 KB。
# part_size=100*1024,
# # 设置下载进度回调函数。
# progress_callback=percentage,
# # 如果使用num_threads设置并发下载线程数,请将oss2.defaults.connection_pool_size设置为大于或等于并发下载线程数。默认并发下载线程数为1。
# num_threads=4)
using Aliyun.OSS;
using Aliyun.OSS.Common;
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称,例如examplebucket。
var bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
var objectName = "exampleobject.txt";
// 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中(D:\\localpath)。如果指定的本地文件存在会覆盖,不存在则新建。
// 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
var downloadFilename = "D:\\localpath\\examplefile.txt";
// 设置断点记录文件的完整路径,例如D:\\localpath\\examplefile.txt.dcp。
// 只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
var checkpointDir = "D:\\localpath\\examplefile.txt.dcp";
// 填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。
const string region = "cn-hangzhou";
// 创建ClientConfiguration实例,按照您的需要修改默认参数。
var conf = new ClientConfiguration();
// 设置v4签名。
conf.SignatureVersion = SignatureVersion.V4;
// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
// 通过DownloadObjectRequest设置多个参数。
DownloadObjectRequest request = new DownloadObjectRequest(bucketName, objectName, downloadFilename)
{
// 指定下载的分片大小,单位为字节。
PartSize = 8 * 1024 * 1024,
// 指定并发线程数。
ParallelThreadCount = 3,
// checkpointDir用于保存断点续传进度信息。如果某一分片下载失败,再次下载时会根据文件中记录的点继续下载。如果checkpointDir为null,断点续传功能不会生效,每次失败后都会重新下载。
CheckpointDir = checkpointDir,
};
// 断点续传下载。
client.ResumableDownloadObject(request);
Console.WriteLine("Resumable download object:{0} succeeded", objectName);
}
catch (OssException ex)
{
Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
Console.WriteLine("Failed with error info: {0}", ex.Message);
}
#import "DownloadService.h"
#import "OSSTestMacros.h"
@implementation DownloadRequest
@end
@implementation Checkpoint
- (instancetype)copyWithZone:(NSZone *)zone {
Checkpoint *other = [[[self class] allocWithZone:zone] init];
other.etag = self.etag;
other.totalExpectedLength = self.totalExpectedLength;
return other;
}
@end
@interface DownloadService()<NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
@property (nonatomic, strong) NSURLSession *session; // 网络会话。
@property (nonatomic, strong) NSURLSessionDataTask *dataTask; // 数据请求任务。
@property (nonatomic, copy) DownloadFailureBlock failure; // 请求出错。
@property (nonatomic, copy) DownloadSuccessBlock success; // 请求成功。
@property (nonatomic, copy) DownloadProgressBlock progress; // 下载进度。
@property (nonatomic, copy) Checkpoint *checkpoint; // 检查节点。
@property (nonatomic, copy) NSString *requestURLString; // 文件资源地址,用于下载请求。
@property (nonatomic, copy) NSString *headURLString; // 文件资源地址,用于head请求。
@property (nonatomic, copy) NSString *targetPath; // 文件存储路径。
@property (nonatomic, assign) unsigned long long totalReceivedContentLength; // 已下载文件大小。
@property (nonatomic, strong) dispatch_semaphore_t semaphore;
@end
@implementation DownloadService
- (instancetype)init
{
self = [super init];
if (self) {
NSURLSessionConfiguration *conf = [NSURLSessionConfiguration defaultSessionConfiguration];
conf.timeoutIntervalForRequest = 15;
NSOperationQueue *processQueue = [NSOperationQueue new];
_session = [NSURLSession sessionWithConfiguration:conf delegate:self delegateQueue:processQueue];
_semaphore = dispatch_semaphore_create(0);
_checkpoint = [[Checkpoint alloc] init];
}
return self;
}
// DownloadRequest是下载逻辑的核心。
+ (instancetype)downloadServiceWithRequest:(DownloadRequest *)request {
DownloadService *service = [[DownloadService alloc] init];
if (service) {
service.failure = request.failure;
service.success = request.success;
service.requestURLString = request.sourceURLString;
service.headURLString = request.headURLString;
service.targetPath = request.downloadFilePath;
service.progress = request.downloadProgress;
if (request.checkpoint) {
service.checkpoint = request.checkpoint;
}
}
return service;
}
/**
* 通过Head方法获取文件信息。OSS将文件的ETag和本地checkpoint中保存的ETag进行对比,并返回对比结果。
*/
- (BOOL)getFileInfo {
__block BOOL resumable = NO;
NSURL *url = [NSURL URLWithString:self.headURLString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
[request setHTTPMethod:@"HEAD"];
// 处理Object相关信息,例如ETag用于断点续传时进行预检查,content-length用于计算下载进度。
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"获取文件meta信息失败,error : %@", error);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSString *etag = [httpResponse.allHeaderFields objectForKey:@"Etag"];
if ([self.checkpoint.etag isEqualToString:etag]) {
resumable = YES;
} else {
resumable = NO;
}
}
dispatch_semaphore_signal(self.semaphore);
}];
[task resume];
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
return resumable;
}
/**
* 获取本地文件的大小。
*/
- (unsigned long long)fileSizeAtPath:(NSString *)filePath {
unsigned long long fileSize = 0;
NSFileManager *dfm = [NSFileManager defaultManager];
if ([dfm fileExistsAtPath:filePath]) {
NSError *error = nil;
NSDictionary *attributes = [dfm attributesOfItemAtPath:filePath error:&error];
if (!error && attributes) {
fileSize = attributes.fileSize;
} else if (error) {
NSLog(@"error: %@", error);
}
}
return fileSize;
}
- (void)resume {
NSURL *url = [NSURL URLWithString:self.requestURLString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
[request setHTTPMethod:@"GET"];
BOOL resumable = [self getFileInfo]; // 如果resumable返回NO,表明不满足断点续传的条件。
if (resumable) {
self.totalReceivedContentLength = [self fileSizeAtPath:self.targetPath];
NSString *requestRange = [NSString stringWithFormat:@"bytes=%llu-", self.totalReceivedContentLength];
[request setValue:requestRange forHTTPHeaderField:@"Range"];
} else {
self.totalReceivedContentLength = 0;
}
if (self.totalReceivedContentLength == 0) {
[[NSFileManager defaultManager] createFileAtPath:self.targetPath contents:nil attributes:nil];
}
self.dataTask = [self.session dataTaskWithRequest:request];
[self.dataTask resume];
}
- (void)pause {
[self.dataTask cancel];
self.dataTask = nil;
}
- (void)cancel {
[self.dataTask cancel];
self.dataTask = nil;
[self removeFileAtPath: self.targetPath];
}
- (void)removeFileAtPath:(NSString *)filePath {
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtPath:self.targetPath error:&error];
if (error) {
NSLog(@"remove file with error : %@", error);
}
}
#pragma mark - NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
// 判断下载任务是否完成,然后将结果返回给上层业务。
didCompleteWithError:(nullable NSError *)error {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
if ([httpResponse isKindOfClass:[NSHTTPURLResponse class]]) {
if (httpResponse.statusCode == 200) {
self.checkpoint.etag = [[httpResponse allHeaderFields] objectForKey:@"Etag"];
self.checkpoint.totalExpectedLength = httpResponse.expectedContentLength;
} else if (httpResponse.statusCode == 206) {
self.checkpoint.etag = [[httpResponse allHeaderFields] objectForKey:@"Etag"];
self.checkpoint.totalExpectedLength = self.totalReceivedContentLength + httpResponse.expectedContentLength;
}
}
if (error) {
if (self.failure) {
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:error.userInfo];
[userInfo oss_setObject:self.checkpoint forKey:@"checkpoint"];
NSError *tError = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
self.failure(tError);
}
} else if (self.success) {
self.success(@{@"status": @"success"});
}
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)dataTask.response;
if ([httpResponse isKindOfClass:[NSHTTPURLResponse class]]) {
if (httpResponse.statusCode == 200) {
self.checkpoint.totalExpectedLength = httpResponse.expectedContentLength;
} else if (httpResponse.statusCode == 206) {
self.checkpoint.totalExpectedLength = self.totalReceivedContentLength + httpResponse.expectedContentLength;
}
}
completionHandler(NSURLSessionResponseAllow);
}
// 将接收到的网络数据以追加上传的方式写入到文件中,并更新下载进度。
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.targetPath];
[fileHandle seekToEndOfFile];
[fileHandle writeData:data];
[fileHandle closeFile];
self.totalReceivedContentLength += data.length;
if (self.progress) {
self.progress(data.length, self.totalReceivedContentLength, self.checkpoint.totalExpectedLength);
}
}
@end
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* 初始化OSS账号信息 */
/* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
std::string Endpoint = "yourEndpoint";
/* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
std::string Region = "yourRegion";
/* 填写Bucket名称,例如examplebucket。*/
std::string BucketName = "examplebucket";
/* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。*/
std::string ObjectName = "exampledir/exampleobject.txt";
/* 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中(D:\\localpath)。如果指定的本地文件存在会覆盖,不存在则新建。*/
/* 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。*/
std::string DownloadFilePath = "D:\\localpath\\examplefile.txt";
/* 设置断点记录文件所在的目录,并确保指定的目录已存在,例如D:\\localpath。*/
/* 只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。*/
std::string CheckpointFilePath = "D:\\localpath";
/* 初始化网络等资源。*/
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
/* 断点续传下载。*/
DownloadObjectRequest request(BucketName, ObjectName, DownloadFilePath, CheckpointFilePath);
auto outcome = client.ResumableDownloadObject(request);
if (!outcome.isSuccess()) {
/* 异常处理。*/
std::cout << "ResumableDownloadObject fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* 释放网络等资源。*/
ShutdownSdk();
return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
const char *endpoint = "yourEndpoint";
/* 填写Bucket名称,例如examplebucket。*/
const char *bucket_name = "examplebucket";
/* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。*/
const char *object_name = "exampledir/exampleobject.txt";
/* 填写本地文件的完整路径。*/
const char *local_filename = "yourLocalFilename";
/* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
options->config = oss_config_create(options->pool);
/* 用char*类型的字符串初始化aos_string_t类型。*/
aos_str_set(&options->config->endpoint, endpoint);
/* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
//需要额外配置以下两个参数
aos_str_set(&options->config->region, region);
options->config->signature_version = 4;
/* 是否使用了CNAME。0表示不使用。*/
options->config->is_cname = 0;
/* 用于设置网络相关参数,比如超时时间等。*/
options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
/* 在程序入口调用aos_http_io_initialize方法来初始化网络、内存等全局资源。*/
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
/* 用于内存管理的内存池(pool),等价于apr_pool_t。其实现代码在apr库中。*/
aos_pool_t *pool;
/* 重新创建一个内存池,第二个参数是NULL,表示没有继承其它内存池。*/
aos_pool_create(&pool, NULL);
/* 创建并初始化options,该参数包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全局配置信息。*/
oss_request_options_t *oss_client_options;
/* 在内存池中分配内存给options。*/
oss_client_options = oss_request_options_create(pool);
/* 初始化Client的选项oss_client_options。*/
init_options(oss_client_options);
/* 初始化参数。*/
aos_string_t bucket;
aos_string_t object;
aos_string_t file;
aos_table_t *headers = NULL;
aos_table_t *resp_headers = NULL;
aos_status_t *resp_status = NULL;
oss_resumable_clt_params_t *clt_params;
aos_str_set(&bucket, bucket_name);
aos_str_set(&object, object_name);
aos_str_set(&file, local_filename);
/* 断点续传文件。*/
clt_params = oss_create_resumable_clt_params_content(pool, 1024 * 100, 3, AOS_TRUE, NULL);
resp_status = oss_resumable_download_file(oss_client_options, &bucket, &object, &file, headers, NULL, clt_params, NULL, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("download succeeded\n");
} else {
printf("download failed\n");
}
/* 释放内存池,相当于释放了请求过程中各资源分配的内存。*/
aos_pool_destroy(pool);
/* 释放之前分配的全局资源。*/
aos_http_io_deinitialize();
return 0;
}
require 'aliyun/oss'
client = Aliyun::OSS::Client.new(
# Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
access_key_id: ENV['OSS_ACCESS_KEY_ID'],
access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)
# 填写Bucket名称,例如examplebucket。
bucket = client.get_bucket('examplebucket')
# key填写Object完整路径,Object完整路径中不能包含Bucket名称,例如exampledir/example.zip。
# file填写本地文件的完整路径,例如/tmp/example.zip。
bucket.resumable_download('exampledir/example.zip', '/tmp/example.zip') do |p|
puts "Progress: #{p}"
end
bucket.resumable_download(
'exampledir/example.zip', '/tmp/example.zip',
# cpt_file填写用于记录断点信息的文件路径。
:part_size => 100 * 1024, :cpt_file => '/tmp/example.zip.cpt') { |p|
puts "Progress: #{p}"
}
package main
import (
"context"
"flag"
"log"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
// 定义全局变量
var (
region string // 存储区域
bucketName string // 存储空间名称
objectName string // 对象名称
)
// init函数用于初始化命令行参数
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
flag.StringVar(&objectName, "src-object", "", "The name of the source object.")
}
func main() {
// 解析命令行参数
flag.Parse()
// 检查bucket名称是否为空
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, bucket name required")
}
// 检查region是否为空
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, region required")
}
// 检查源对象名称是否为空
if len(objectName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, src object name required")
}
// 配置OSS客户端
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
// 创建OSS客户端
client := oss.NewClient(cfg)
// 创建下载器
d := client.NewDownloader()
// 构建获取对象的请求
request := &oss.GetObjectRequest{
Bucket: oss.Ptr(bucketName), // 存储空间名称
Key: oss.Ptr(objectName), // 对象名称
}
// 定义本地文件路径
localFile := "local-file"
// 设置下载器选项
downloaderOptions := func(do *oss.DownloaderOptions) {
do.EnableCheckpoint = true // 启用记录断点下载信息
do.CheckpointDir = "./checkpoint" // 指定断点下载信息存储的目录
do.UseTempFile = true // 下载文件时使用临时文件
}
// 执行下载文件的请求
result, err := d.DownloadFile(context.TODO(), request, localFile, downloaderOptions)
if err != nil {
log.Fatalf("failed to download file %v", err)
}
// 打印下载成功的信息
log.Printf("download file %s to local-file successfully, size: %d", objectName, result.Written)
}
更多参考
如何在开启了版本控制的Bucket中下载文件,请参见开启版本控制下Object的操作。
如果您希望将私有Bucket的Object提供给第三方进行下载,请通过STS临时访问凭证或签名URL的方式授权第三方下载文件。具体操作,请参见授权给第三方下载。
- 本页导读 (1)
- 前提条件
- 注意事项
- 使用阿里云SDK
- 更多参考