在下載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.ClientBuilderConfiguration;
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.common.comm.SignVersion;
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();
}
}
}
}
import argparse
import alibabacloud_oss_v2 as oss
# 建立一個命令列參數解析器,並描述指令碼用途:下載檔案樣本
parser = argparse.ArgumentParser(description="download file sample")
# 添加命令列參數 --region,表示儲存空間所在的地區,必需參數
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令列參數 --bucket,表示要下載檔案的儲存空間名稱,必需參數
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令列參數 --endpoint,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)
# 添加命令列參數 --file_path,表示下載檔案儲存的本地路徑,必需參數,例如“/Users/yourLocalPath/yourFileName”
parser.add_argument('--file_path', help='The path to save the downloaded file.', required=True)
def main():
# 解析命令列提供的參數,擷取使用者輸入的值
args = parser.parse_args()
# 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
# 使用SDK的預設配置建立設定物件,並設定認證提供者
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
# 設定設定物件的地區屬性,根據使用者提供的命令列參數
cfg.region = args.region
# 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
if args.endpoint is not None:
cfg.endpoint = args.endpoint
# 使用上述配置初始化OSS用戶端,準備與OSS互動
client = oss.Client(cfg)
# 建立一個用於下載檔案的對象,並設定進階選項
downloader = client.downloader(
use_temp_file=True, # 使用臨時檔案
enable_checkpoint=True, # 啟用斷點續傳
checkpoint_dir=args.file_path, # 儲存斷點續傳記錄檔案的目錄
verify_data=True # 是否校正資料
)
# 調用方法執行檔案下載操作
result = downloader.download_file(
oss.GetObjectRequest(
bucket=args.bucket, # 指定目標儲存空間
key=args.key, # 指定檔案在OSS中的名稱
),
filepath=args.file_path # 指定下載檔案儲存的本地路徑
)
# 列印下載結果的相關資訊,包括已寫入的位元組數
print(f'written: {result.written}')
# 當此指令碼被直接執行時,調用main函數開始處理邏輯
if __name__ == "__main__":
main() # 指令碼進入點,控製程序流程從這裡開始
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)
}
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}"
}
更多參考
如何在開啟了版本控制的Bucket中下載檔案,請參見開啟版本控制下Object的操作。
如果您希望將私人Bucket的Object提供給第三方進行下載,請通過STS臨時訪問憑證或簽名URL的方式授權第三方下載檔案。具體操作,請參見授權給第三方下載。