すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:オブジェクトをファイルとしてダウンロードする

最終更新日:Jul 05, 2025

このトピックでは、Object Storage Service (OSS) バケットからローカルデバイスにオブジェクトをすばやくダウンロードする方法について説明します。

使用方法

このトピックのサンプルコードでは、中国 (杭州) リージョンのリージョン ID cn-hangzhou を使用しています。デフォルトでは、パブリックエンドポイントを使用してバケット内のリソースにアクセスします。バケットが配置されているのと同じリージョン内の他の Alibaba Cloud サービスからバケット内のリソースにアクセスする場合は、内部エンドポイントを使用します。 OSS でサポートされているリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。

権限

デフォルトでは、Alibaba Cloud アカウントにはフルパーミッションがあります。Alibaba Cloud アカウントの RAM ユーザーまたは RAM ロールには、デフォルトではパーミッションがありません。Alibaba Cloud アカウントまたはアカウント管理者は、「RAM ポリシー」または「バケットポリシー」を通じて操作権限を付与する必要があります。

API

アクション

定義

GetObject

oss:GetObject

オブジェクトをダウンロードします。

oss:GetObjectVersion

オブジェクトをダウンロードするときに、versionId を使用してオブジェクトバージョンを指定する場合、この権限が必要です。

kms:Decrypt

オブジェクトをダウンロードするときに、オブジェクトメタデータに X-Oss-Server-Side-Encryption: KMS が含まれている場合、この権限が必要です。

メソッド定義

get_object(request: GetObjectRequest, **kwargs) → GetObjectResult

リクエストパラメーター

パラメーター

タイプ

説明

request

GetObjectRequest

リクエストパラメーター。詳細については、GetObjectRequest をご参照ください。

レスポンスパラメーター

タイプ

説明

GetObjectResult

戻り値。詳細については、GetObjectResult をご参照ください。

簡単なダウンロードメソッドの完全な定義については、「get_object」をご参照ください。

サンプルコード

次のサンプルコードは、オブジェクトをローカルデバイスにダウンロードします。

import argparse
import alibabacloud_oss_v2 as oss
import os

# Create a command-line parameter parser.
parser = argparse.ArgumentParser(description="get object sample")

# Specify the --region parameter to indicate the region in which the bucket is located. This parameter is required.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# Specify the --bucket parameter to indicate the name of the bucket. This command line parameter is required. 
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# Specify the --endpoint parameter to indicate the endpoint of the region in which the bucket is located. This parameter is optional.
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# Specify the --key parameter to indicate the name of the object. This parameter is required.
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # Parse the command-line parameters.
    args = parser.parse_args()

    # Obtain access credentials from environment variables for authentication.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Load the default configuration of the SDK and specify the credential provider.
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # Specify the region in which the bucket is located.
    cfg.region = args.region

    # If an endpoint is provided, specify the endpoint in the configuration object.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Use the configuration to create an OSSClient instance.
    client = oss.Client(cfg)

    # Execute the request to download the object, and specify the bucket name and object name.
    result = client.get_object(oss.GetObjectRequest(
        bucket=args.bucket,  # Specify the name of the bucket.
        key=args.key,  # Specify object key.
    ))

    # Display the response to check whether the request is successful.
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content length: {result.content_length},'
          f' content range: {result.content_range},'
          f' content type: {result.content_type},'
          f' etag: {result.etag},'
          f' last modified: {result.last_modified},'
          f' content md5: {result.content_md5},'
          f' cache control: {result.cache_control},'
          f' content disposition: {result.content_disposition},'
          f' content encoding: {result.content_encoding},'
          f' expires: {result.expires},'
          f' hash crc64: {result.hash_crc64},'
          f' storage class: {result.storage_class},'
          f' object type: {result.object_type},'
          f' version id: {result.version_id},'
          f' tagging count: {result.tagging_count},'
          f' server side encryption: {result.server_side_encryption},'
          f' server side data encryption: {result.server_side_data_encryption},'
          f' next append position: {result.next_append_position},'
          f' expiration: {result.expiration},'
          f' restore: {result.restore},'
          f' process status: {result.process_status},'
          f' delete marker: {result.delete_marker},'
    )

    # ========== Method 1: Read the entire object ==========
    with result.body as body_stream:
        data = body_stream.read()
        print(f"The object is read. Data length: {len(data)} bytes")

        path = "./get-object-sample.txt"
        with open(path, 'wb') as f:
            f.write(data)
        print(f"The object is downloaded and saved to a local path: {path}")

    # # ========== Method 2: Read the object in chunks ==========
    # with result.body as body_stream:
    #     chunk_path = "./get-object-sample-chunks.txt"
    #     total_size = 0

    #     with open(chunk_path, 'wb') as f:
    #         # Use 256KB block size (you can adjust the block_size parameter as needed)
    #         for chunk in body_stream.iter_bytes(block_size=256 * 1024):
    #             f.write(chunk)
    #             total_size += len(chunk)
    #             print(f"Received data block: {len(chunk)} bytes | Total: {total_size} bytes")

    #     print(f"The object is downloaded and saved to the local path: {chunk_path}")

# Call the main function when the script is directly run.
if __name__ == "__main__":
    main()  # The entry point of the script. When the script is directly run, the main function is called.

一般的なシナリオ

条件付きダウンロード

バケットから単一のオブジェクトをダウンロードする場合、オブジェクトの最終更新時刻または ETag に基づいて条件を指定できます。これらの条件が満たされた場合にのみ、オブジェクトがダウンロードされます。そうでない場合は、エラーが返され、ダウンロード操作はトリガーされません。これにより、不要なネットワーク転送とリソース消費が削減され、ダウンロード効率が向上します。

次の表に、使用可能な条件を示します。

説明
  • if_modified_since と if_unmodified_since は共存できます。 if_match と if_none_match も共存できます。

  • client.get_object_meta メソッドを使用して、ETag を取得できます。

パラメーター

説明

if_modified_since

指定された時刻がオブジェクトの最終更新時刻より前の場合、オブジェクトをダウンロードできます。そうでない場合は、304 Not Modified が返されます。

if_unmodified_since

指定された時刻がオブジェクトの最終更新時刻以降の場合、オブジェクトをダウンロードできます。そうでない場合は、412 Precondition Failed が返されます。

if_match

指定された ETag がオブジェクトの ETag と一致する場合、オブジェクトをダウンロードできます。そうでない場合は、412 Precondition Failed が返されます。

if_none_match

指定された ETag がオブジェクトの ETag と一致しない場合、オブジェクトをダウンロードできます。そうでない場合は、304 Not Modified が返されます。

次のサンプルコードは、条件付きダウンロードを実装する方法の例を示しています。

import argparse
import alibabacloud_oss_v2 as oss
from datetime import datetime, timezone

# Create a parser for parsing command-line arguments and describe the purpose of the script.
parser = argparse.ArgumentParser(description="get object to file sample")

# Specify the --region parameter to indicate the region in which the bucket is located. This parameter is required.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# Specify the --bucket parameter to indicate the name of the bucket in which the object is stored. This parameter is required.
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# Specify the --endpoint parameter to indicate the endpoint of the region in which the bucket is located. This parameter is optional.
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# Specify the --key parameter to indicate the name of the object. This parameter is required.
parser.add_argument('--key', help='The name of the object.', required=True)
# Specify the --file_path parameter to indicate the path to which the object is downloaded. This parameter is required.
parser.add_argument('--file_path', help='The path of the file to save the downloaded content.', required=True)

def main():
    # Parse the command-line parameters to obtain the specified values.
    args = parser.parse_args()

    # Obtain access credentials from environment variables for authentication.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Use the default configuration to create a configuration object (cfg) and specify the credential provider.
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    
    # Set the region attribute of the cfg object to the region in the parser.
    cfg.region = args.region

    # If a custom endpoint is provided, update the endpoint attribute of the cfg object with the provided endpoint.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Use the preceding configuration to initialize the OSSClient instance.
    client = oss.Client(cfg)

    # Define if_modified_since time.
    # Only objects modified after this time will be returned.
    if_modified_since = datetime(2024, 10, 1, 12, 0, 0, tzinfo=timezone.utc)

    # Assuming the ETag is DA5223EFCD7E0353BE08866700000000, if the specified ETag matches the ETag of the object, the IfMatch condition is met and the download will be triggered.
    etag = "\"DA5223EFCD7E0353BE08866700000000\""

    # Execute the request to download the object and save it to a local file.
    result = client.get_object_to_file(
        oss.GetObjectRequest(
            bucket=args.bucket,  # Specify the name of the bucket.
            key=args.key,        # Specify the object key.
            if_modified_since=if_modified_since,  # Only objects modified after the specified time will be returned.
            if_match=etag,       # Only objects with matching ETag will be returned.
        ),
        args.file_path  # Specify the local path to save the downloaded file.
    )

    # Display the response information, including status code, request ID, etc.
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content length: {result.content_length},'
          f' content range: {result.content_range},'
          f' content type: {result.content_type},'
          f' etag: {result.etag},'
          f' last modified: {result.last_modified},'
          f' content md5: {result.content_md5},'
          f' cache control: {result.cache_control},'
          f' content disposition: {result.content_disposition},'
          f' content encoding: {result.content_encoding},'
          f' expires: {result.expires},'
          f' hash crc64: {result.hash_crc64},'
          f' storage class: {result.storage_class},'
          f' object type: {result.object_type},'
          f' version id: {result.version_id},'
          f' tagging count: {result.tagging_count},'
          f' server side encryption: {result.server_side_encryption},'
          f' server side data encryption: {result.server_side_data_encryption},'
          f' next append position: {result.next_append_position},'
          f' expiration: {result.expiration},'
          f' restore: {result.restore},'
          f' process status: {result.process_status},'
          f' delete marker: {result.delete_marker},'
          f' server time: {result.headers.get("x-oss-server-time")},'
    )

# Call the main function to start the processing logic when the script is directly run.
if __name__ == "__main__":
    main()  # Specify the entry point of the script. The control flow starts here.

ダウンロードの進捗状況を表示する

オブジェクトをダウンロードするときは、プログレスバーを使用してダウンロードの進捗状況をリアルタイムで監視できます。進捗状況の監視は、ダウンロードタスクの完了に時間がかかる場合に、タスクが停止しているかどうかを確認するのに役立ちます。

次のサンプルコードは、get_object_to_file を使用してオブジェクトをローカルファイルにダウンロードするときに、プログレスバーを使用してダウンロードの進捗状況を表示する方法を示しています。

import argparse
import alibabacloud_oss_v2 as oss

# Create a parser for parsing command-line arguments and describe the purpose of the script.
parser = argparse.ArgumentParser(description="get object sample")

# Specify the --region parameter to indicate the region in which the bucket is located. This parameter is required.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# Specify the --bucket parameter to indicate the name of the bucket in which the object is stored. This parameter is required.
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# Specify the --endpoint parameter to indicate the endpoint of the region in which the bucket is located. This parameter is optional.
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# Specify the --key parameter to indicate the name of the object. This parameter is required. 
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # Parse the command-line parameters to obtain the specified values.
    args = parser.parse_args()

    # Obtain access credentials from environment variables for authentication.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Use the default configuration to create a configuration object (cfg) and specify the credential provider.
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # Set the region attribute of the cfg object to the region in the parser.
    cfg.region = args.region

    # If a custom endpoint is provided, update the endpoint attribute of the cfg object with the provided endpoint.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Use the preceding configuration to initialize the OSSClient instance.
    client = oss.Client(cfg)

    # Define a dictionary variable progress_state to store the download progress status, with an initial value of 0.
    progress_state = {'saved': 0}
    
    # Define the progress callback function _progress_fn.
    def _progress_fn(n, written, total):
        # Use a dictionary to store the accumulated written bytes.
        progress_state['saved'] += n

        # Calculate the current download percentage by dividing the number of bytes written by the total bytes and truncating the result to an integer.
        rate = int(100 * (float(written) / float(total)))

        # Print the current download progress. Use \r to return to the start of the line, achieving real-time refresh in the terminal.
        # end='' suppresses line breaks, enabling subsequent prints to overwrite the current line.
        print(f'\r{rate}% ', end='')

    # Execute the request to download the object, and specify the bucket name, object name and the progress callback function.
    result = client.get_object_to_file(
        oss.GetObjectRequest(
            bucket=args.bucket,  # Specify the name of the bucket.
            key=args.key,        # Specify the object key.
            progress_fn=_progress_fn, # Specify the progress callback function.
        ),
        "/local/dir/example", # Specify the local path to save the file.
    )

    # Display the response information.
    print(vars(result))

# Call the main function to start the processing logic when the script is directly run.
if __name__ == "__main__":
    main()  # Specify the entry point of the script. The control flow starts here.

次のサンプルコードは、get_object を使用してオブジェクトをストリーミングするときに、プログレスバーを使用してダウンロードの進捗状況を表示する方法を示しています。

import argparse
import alibabacloud_oss_v2 as oss
import os

# Create a command-line parameter parser.
parser = argparse.ArgumentParser(description="get object sample")

# Specify the --region parameter to indicate the region in which the bucket is located. This parameter is required.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# Specify the --bucket parameter to indicate the name of the bucket. This command line parameter is required.
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# Specify the --endpoint parameter to indicate the endpoint of the region in which the bucket is located. This parameter is optional.
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# Specify the --key parameter to indicate the name of the object. This parameter is required.
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # Parse the command line parameters.
    args = parser.parse_args()

    # Obtain access credentials from environment variables for authentication.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Load the default configuration of the SDK and specify the credential provider.
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # Specify the region in which the bucket is located.
    cfg.region = args.region

    # If an endpoint is provided, specify the endpoint in the configuration object.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Use the configuration to create an OSSClient instance.
    client = oss.Client(cfg)

    # Execute the request to download the object, and specify the bucket name and object name.
    result = client.get_object(oss.GetObjectRequest(
        bucket=args.bucket,  # Specify the name of the bucket.
        key=args.key,  # Specify the object key.
    ))

    # Get the total size of the file in bytes from the object response result.
    total_size = result.content_length

    # Initialize the progress counter to 0, used to record the amount of data downloaded.
    progress_save_n = 0

    # Iterate through data blocks in the response body to implement block-by-block data reading.
    for d in result.body.iter_bytes():
        # Accumulate the length of the current data block into the total downloaded amount.
        progress_save_n += len(d)

        # Calculate the current download percentage by computing the ratio of the downloaded amount to the total size and rounding to the nearest integer.
        rate = int(100 * (float(progress_save_n) / float(total_size)))

        # Print the current download progress. Utilize \r (carriage return) to reposition the cursor at the beginning of the line, enabling real-time progress updates within the command-line interface.
        # end='' suppresses line breaks, enabling subsequent prints to overwrite the current line.
        print(f'\r{rate}% ', end='')

    # Print all attributes of the result object for debugging purposes or to examine the complete response content.
    print(vars(result))


# Call the main function to start the processing logic when the script is directly run.
if __name__ == "__main__":
    main()  # Specify the entry point of the script. The control flow starts here.

オブジェクトをローカルファイルにバッチダウンロードする

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import alibabacloud_oss_v2 as oss
import os
import sys
import threading
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
from typing import List, Tuple, Optional
import signal

class DownloadTask:
    """ダウンロードタスククラス"""
    def __init__(self, object_key: str, local_path: str, size: int):
        self.object_key = object_key
        self.local_path = local_path
        self.size = size

class DownloadResult:
    """ダウンロード結果クラス"""
    def __init__(self, object_key: str, success: bool = False, error: Optional[str] = None, size: int = 0):
        self.object_key = object_key
        self.success = success
        self.error = error
        self.size = size

class BatchDownloader:
    """バッチダウンローダー"""

    def __init__(self, client: oss.Client, bucket: str, max_workers: int = 5):
        self.client = client
        self.bucket = bucket
        self.max_workers = max_workers
        self.stop_event = threading.Event()

    def list_objects(self, prefix: str = "", max_keys: int = 1000) -> List[DownloadTask]:
        """バケット内の指定されたプレフィックスを持つすべてのオブジェクトをリストします"""
        tasks = []
        continuation_token = None

        print(f"バケット内のファイルをスキャンしています...")

        while not self.stop_event.is_set():
            try:
                # オブジェクトをリストするためのリクエストを作成します。
                request = oss.ListObjectsV2Request(
                    bucket=self.bucket,
                    prefix=prefix,
                    max_keys=max_keys,
                    continuation_token=continuation_token
                )

                # リスト操作を実行します。
                result = self.client.list_objects_v2(request)

                # リスト結果を処理します。
                for obj in result.contents:
                    # フォルダーオブジェクト (末尾が '/' で、サイズが 0 バイト) をスキップします。
                    if obj.key.endswith('/') and obj.size == 0:
                        continue

                    # ローカルファイルパスを計算します。
                    relative_path = obj.key[len(prefix):] if prefix else obj.key

                    tasks.append(DownloadTask(
                        object_key=obj.key,
                        local_path=relative_path,
                        size=obj.size
                    ))

                # もっとオブジェクトがあるかどうかを確認します。
                if not result.next_continuation_token:
                    break
                continuation_token = result.next_continuation_token

            except Exception as e:
                raise Exception(f"オブジェクトのリストに失敗しました: {str(e)}")

        return tasks

    def download_file(self, task: DownloadTask, local_dir: str) -> DownloadResult:
        """単一のファイルをダウンロードします"""
        result = DownloadResult(task.object_key, size=task.size)

        try:
            # ローカルファイルのフルパスを計算します。
            full_local_path = os.path.join(local_dir, task.local_path)

            # ローカルファイルのディレクトリを作成します。
            os.makedirs(os.path.dirname(full_local_path), exist_ok=True)

            # ファイルが存在するかどうか、およびサイズの一貫性を検証して、再開可能な転送を有効にします。
            if os.path.exists(full_local_path):
                local_size = os.path.getsize(full_local_path)
                if local_size == task.size:
                    result.success = True
                    return result

            # ダウンロードリクエストを作成します。
            get_request = oss.GetObjectRequest(
                bucket=self.bucket,
                key=task.object_key
            )

            # ダウンロード操作を実行します。
            response = self.client.get_object(get_request)

            # ファイルを保存します。
            with open(full_local_path, 'wb') as f:
                with response.body as body_stream:
                    # ブロック単位で読み書きします
                    for chunk in body_stream.iter_bytes(block_size=1024 * 1024):  # 1MB ブロック
                        if self.stop_event.is_set():
                            raise Exception("ダウンロードが中断されました")
                        f.write(chunk)

            result.success = True

        except Exception as e:
            result.error = str(e)
            # ダウンロードに失敗した場合は、不完全なファイルを削除します。
            try:
                if os.path.exists(full_local_path):
                    os.remove(full_local_path)
            except:
                pass

        return result

    def batch_download(self, tasks: List[DownloadTask], local_dir: str) -> List[DownloadResult]:
        """バッチダウンロードを実行します"""
        results = []
        completed = 0
        total = len(tasks)

        print(f"{self.max_workers} 個の同時スレッドを使用して、{total} 個のファイルのダウンロードを開始しています...")

        with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            # すべてのダウンロードタスクを送信します。
            future_to_task = {
                executor.submit(self.download_file, task, local_dir): task
                for task in tasks
            }

            # 完了したタスクを処理します。
            for future in as_completed(future_to_task):
                if self.stop_event.is_set():
                    break

                task = future_to_task[future]
                try:
                    result = future.result()
                    results.append(result)
                    completed += 1

                    # 進捗状況を表示します。
                    if result.success:
                        print(f"✓ [{completed}/{total}] {result.object_key} ({self.format_bytes(result.size)})")
                    else:
                        print(f"✗ [{completed}/{total}] {result.object_key} - エラー: {result.error}")

                except Exception as e:
                    result = DownloadResult(task.object_key, error=str(e), size=task.size)
                    results.append(result)
                    completed += 1
                    print(f"✗ [{completed}/{total}] {task.object_key} - 例外: {str(e)}")

        return results

    def stop(self):
        """ダウンロードを停止します"""
        self.stop_event.set()
        print("\nダウンロードを停止しています...")

    @staticmethod
    def format_bytes(bytes_size: int) -> str:
        """バイトを読みやすい形式にフォーマットします"""
        for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
            if bytes_size < 1024.0:
                return f"{bytes_size:.1f} {unit}"
            bytes_size /= 1024.0
        return f"{bytes_size:.1f} PB"

def signal_handler(signum, frame):
    """シグナルハンドラー"""
    print(f"\nシグナル {signum} を受信しました。停止しています...")
    if hasattr(signal_handler, 'downloader'):
        signal_handler.downloader.stop()
    sys.exit(0)

def main():
    # コマンドラインパラメーターパーサーを作成します。
    parser = argparse.ArgumentParser(description="OSS バッチダウンロードツール")

    # コマンドラインパラメーターを追加します。
    parser.add_argument('--region', help='バケットが配置されているリージョン', required=True)
    parser.add_argument('--bucket', help='バケットの名前', required=True)
    parser.add_argument('--endpoint', help='カスタムエンドポイント (オプション)')
    parser.add_argument('--prefix', help='ダウンロードするフォルダーのプレフィックス。空の文字列はバケット全体をダウンロードすることを意味します', default="")
    parser.add_argument('--local-dir', help='ローカルダウンロードディレクトリ', default="./downloads")
    parser.add_argument('--workers', help='同時ダウンロード数', type=int, default=5)
    parser.add_argument('--max-keys', help='一度にリストするオブジェクトの最大数', type=int, default=1000)

    # コマンドラインパラメーターを解析します。
    args = parser.parse_args()

    try:
        # 環境変数からアクセス認証情報を取得します。
        credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

        # SDK のデフォルト設定を読み込みます。
        cfg = oss.config.load_default()
        cfg.credentials_provider = credentials_provider
        cfg.region = args.region

        # endpoint パラメーターが指定されている場合は、カスタムエンドポイントを指定します。
        if args.endpoint:
            cfg.endpoint = args.endpoint

        # OSS クライアントを作成します。
        client = oss.Client(cfg)

        # ローカルダウンロードディレクトリを作成します。
        local_dir = getattr(args, 'local_dir')
        os.makedirs(local_dir, exist_ok=True)

        # バッチダウンローダーを作成します。
        downloader = BatchDownloader(client, args.bucket, args.workers)

        # シグナルハンドラーを設定して、安全なシャットダウンプロシージャを有効にします。
        signal_handler.downloader = downloader
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        print(f"バッチダウンロードを開始しています")
        print(f"バケット: {args.bucket}")
        print(f"プレフィックス: '{args.prefix}' {'(バケット全体)' if not args.prefix else ''}")
        print(f"ローカルディレクトリ: {local_dir}")
        print(f"同時実行数: {args.workers}")
        print("-" * 50)

        # ダウンロードするすべてのオブジェクトをリストします。
        tasks = downloader.list_objects(args.prefix, getattr(args, 'max_keys'))

        if not tasks:
            print("ダウンロードするファイルが見つかりませんでした")
            return

        print(f"{len(tasks)} 個のダウンロード対象ファイルが見つかりました")
        print("-" * 50)

        # バッチダウンロードを実行します。
        start_time = time.time()
        results = downloader.batch_download(tasks, local_dir)
        end_time = time.time()

        # ダウンロード結果をまとめます。
        success_count = sum(1 for r in results if r.success)
        fail_count = len(results) - success_count
        total_size = sum(r.size for r in results if r.success)
        duration = end_time - start_time

        print("-" * 50)
        print(f"ダウンロードが完了しました!")
        print(f"成功: {success_count}")
        print(f"失敗: {fail_count}")
        print(f"合計サイズ: {BatchDownloader.format_bytes(total_size)}")
        print(f"期間: {duration:.2f} 秒")

        if fail_count > 0:
            print(f"\n失敗したファイル:")
            for result in results:
                if not result.success:
                    print(f"  - {result.object_key}: {result.error}")

    except KeyboardInterrupt:
        print("\nユーザーによってダウンロードが中断されました")
        sys.exit(1)
    except Exception as e:
        print(f"エラー: {str(e)}")
        sys.exit(1)

if __name__ == "__main__":
    main()

使用例

# my-bucket バケットからプレフィックス images/2024/ のすべてのオブジェクトをダウンロードします。
python batch_download.py --region cn-hangzhou --bucket my-bucket --prefix images/2024/

# 指定されたローカルディレクトリにダウンロードします。
python batch_download.py --region cn-hangzhou --bucket my-bucket --prefix documents/ --local-dir ./my-downloads

# スループットを向上させるために、ダウンロードの同時実行数を増やします。
python batch_download.py --region cn-hangzhou --bucket my-bucket --prefix videos/ --workers 10

# prefix パラメーターを省略するか、プレフィックスとして空の文字列を指定することにより、バケット内のすべてのオブジェクトをダウンロードします。
python batch_download.py --region cn-hangzhou --bucket my-bucket

# あるいは、空のプレフィックスを明示的に指定します。
python batch_download.py --region cn-hangzhou --bucket my-bucket --prefix ""

出力例

プログラムは、実行中に詳細なダウンロードの進捗状況を表示します。

バッチダウンロードを開始しています
バケット: my-bucket
プレフィックス: 'images/2024/'
ローカルディレクトリ: ./downloads
同時実行数: 5
--------------------------------------------------
バケット内のファイルをスキャンしています...
150 個のダウンロード対象ファイルが見つかりました
--------------------------------------------------
5 個の同時スレッドを使用して、150 個のファイルのダウンロードを開始しています...
✓ [1/150] images/2024/photo1.jpg (2.3 MB)
✓ [2/150] images/2024/photo2.png (1.8 MB)
✗ [3/150] images/2024/photo3.gif - エラー: リクエストタイムアウト
✓ [4/150] images/2024/subfolder/photo4.jpg (3.1 MB)
...
✓ [150/150] images/2024/thumbnails/thumb150.jpg (256.0 KB)
--------------------------------------------------
ダウンロードが完了しました!
成功: 148
失敗: 2
合計サイズ: 1.2 GB
期間: 45.67 秒

失敗したファイル:
  - images/2024/photo3.gif: リクエストタイムアウト
  - images/2024/corrupted.jpg: 無効なレスポンス

関連情報