پرش به مطلب اصلی

بارگذاری چندبخشی آبجکت داخل صندوقچه (Multi-part Upload)

بارگذاری چند بخشی به شما این امکان را می‌دهد تا یک آبجکت را در چند بخش بارگذاری کنید. هر بخش یک تکه‌ی جداگانه از آبجکت است که می‌توانید، به‌طور مستقل و به هر ترتیبی بارگذاری کنید. در زمان عدم موفقیت در بارگذاری هر قسمت، می‌توانید دوباره آن قسمت را بارگذاری کنید بدون این‌که بر قسمت‌های دیگر تاثیر بگذارد. بعد از بارگذاری تمام قسمت‌ها، آبجکت ایجاد می‌شود.

فرآیند یک بارگذاری چند بخشی به‌شکل زیر است (این مراحل در نمونه کد زیر توسط کتابخانه aws s3 انجام می‌شود):

۱. ارسال Request آغاز فرآیند بارگذاری چند بخشی

۲. بارگذاری قسمت‌های تکه‌شده فایل

۳. ارسال درخواست تکمیل بارگذاری (در این مرحله کلیه‌ی بخش‌های فایل تبدیل به یک فایل اصلی شده و فرآیند بارگذاری در این‌جا به اتمام می‌رسد.)

اگر در حین فرآیند بارگذاری چند بخشی از ادامه بارگذاری منصرف شدید باید حتمن فرآیند را متوقف کنید تا حجم ذخیره شده توسط بخش های فایل ناتمام آزاد شود ، شیوه‌ی متوقف کردن بارگذاری چند بخشی را در قسمت بعدی راهنما مشاهده کنید.

مولفه‌ها

  • نام صندوقچه
  • نام آبجکت
  • مسیر فایل

نام آبجکت (Key)

نام آبجکت پس از بارگذاری داخل صندوقچه

مسیر فایل (SourceFile)

مسیری که فایل باید بارگذاری شود

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

namespace UploadFileMPULowLevelAPIExample
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;

/// <summary>
/// Uses the Amazon Simploe Storage Service (Amazon S3) low-level API to
/// upload an object from the local system to an Amazon S3 bucket. This
/// example was created using the AWS SDK for .NET verion 3.7 and
/// .NET Core 5.0.
/// </summary>
public class UploadFileMPULowLevelAPI
{
private static IAmazonS3 _s3Client;

private const string BUCKET_NAME = "<BUCKET_NAME>";
private static string LOCAL_PATH = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private const string OBJECT_NAME = "<OBJECT_NAME>";

public static async Task Main()
{
string bucketName = BUCKET_NAME;
string keyName = OBJECT_NAME;
string filePath = $"{LOCAL_PATH}/{keyName}";

var awsCredentials = new Amazon.Runtime.BasicAWSCredentials("<ACCESS-KEY>", "<SECRET-KEY>");
var config = new AmazonS3Config { ServiceURL = "<ENDPOINT>" };
_s3Client = new AmazonS3Client(awsCredentials, config);

Console.WriteLine("Uploading an object...");
await UploadObjectAsync(_s3Client, bucketName, keyName, filePath);
}

/// <summary>
/// Uses the low-level API to upload an object from the local system to
/// to an S3 bucket.
/// </summary>
/// <param name="client">The initialized S3 client object used to
/// perform the multi-part upload.</param>
/// <param name="bucketName">>The name of the bucket to which to upload
/// the file.</param>
/// <param name="keyName">The file name to be used in the
/// destination S3 bucket.</param>
/// <param name="filePath">The path, including the file name of the
/// file to be uploaded to the S3 bucket.</param>
public static async Task UploadObjectAsync(
IAmazonS3 client,
string bucketName,
string keyName,
string filePath)
{
// Create list to store upload part responses.
List<UploadPartResponse> uploadResponses = new ();

// Setup information required to initiate the multipart upload.
InitiateMultipartUploadRequest initiateRequest = new ()
{
BucketName = bucketName,
Key = keyName,
};

// Initiate the upload.
InitiateMultipartUploadResponse initResponse =
await client.InitiateMultipartUploadAsync(initiateRequest);

// Upload parts.
long contentLength = new FileInfo(filePath).Length;
long partSize = 400 * (long)Math.Pow(2, 20); // 400 MB

try
{
Console.WriteLine("Uploading parts");

long filePosition = 0;
for (int i = 1; filePosition < contentLength; i++)
{
UploadPartRequest uploadRequest = new ()
{
BucketName = bucketName,
Key = keyName,
UploadId = initResponse.UploadId,
PartNumber = i,
PartSize = partSize,
FilePosition = filePosition,
FilePath = filePath,
};

// Track upload progress.
uploadRequest.StreamTransferProgress +=
new EventHandler<StreamTransferProgressArgs>(UploadPartProgressEventCallback);

// Upload a part and add the response to our list.
uploadResponses.Add(await client.UploadPartAsync(uploadRequest));

filePosition += partSize;
}

// Setup to complete the upload.
CompleteMultipartUploadRequest completeRequest = new ()
{
BucketName = bucketName,
Key = keyName,
UploadId = initResponse.UploadId,
};
completeRequest.AddPartETags(uploadResponses);

// Complete the upload.
CompleteMultipartUploadResponse completeUploadResponse =
await client.CompleteMultipartUploadAsync(completeRequest);

Console.WriteLine($"Object {keyName} added to {bucketName} bucket");
}
catch (Exception exception)
{
Console.WriteLine($"An AmazonS3Exception was thrown: {exception.Message}");

// Abort the upload.
AbortMultipartUploadRequest abortMPURequest = new ()
{
BucketName = bucketName,
Key = keyName,
UploadId = initResponse.UploadId,
};
await client.AbortMultipartUploadAsync(abortMPURequest);
}
}

/// <summary>
/// Handles the UploadProgress even to display the progress of the
/// S3 multi-part upload.
/// </summary>
/// <param name="sender">The object that raised the event.</param>
/// <param name="e">The event parameters.</param>
public static void UploadPartProgressEventCallback(object sender, StreamTransferProgressArgs e)
{
Console.WriteLine($"{e.TransferredBytes}/{e.TotalBytes}");
}
}
}