다음을 통해 공유


.NET를 사용하여 Blob 업로드

이 문서에서는 .NET용 Azure Storage 클라이언트 라이브러리를 사용하여 Blob을 업로드하는 방법을 보여 줍니다. 파일 경로, 스트림, 이진 개체 또는 텍스트 문자열에서 블록 Blob에 데이터를 업로드할 수 있습니다. Blob 스트림을 열고 여기에 쓰거나 블록 단위로 큰 Blob을 업로드할 수도 있습니다.

필수 조건

환경 설정

기존 프로젝트가 없는 경우, 이 섹션에서는 .NET용 Azure Blob Storage 클라이언트 라이브러리를 사용해서 작동하도록 프로젝트를 설정하는 방법을 보여 줍니다. 이 단계에는 패키지 설치, using 지시문 추가 및 권한이 있는 클라이언트 개체 만들기가 포함됩니다. 자세한 내용은 Azure Blob Storage 및 .NET 시작을 참조하세요.

패키지 설치

프로젝트 디렉터리에서 dotnet add package 명령을 사용하여 Azure Blob Storage 및 Azure ID 클라이언트 라이브러리용 패키지를 설치합니다. Azure 서비스에 암호 없이 연결하려면 Azure.Identity 패키지가 필요합니다.

dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Identity

using 지시문 추가

코드 파일 맨 위에 다음과 같이 using 지시문을 추가합니다.

using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;

이 게시물의 일부 코드 예제에는 using 지시문이 추가로 필요할 수 있습니다.

클라이언트 개체 만들기

Blob Storage에 앱을 연결하려면 BlobServiceClient의 인스턴스를 만듭니다. 다음 예에서는 권한 부여를 위해 DefaultAzureCredential을 사용하여 클라이언트 개체를 만드는 방법을 설명합니다.

public BlobServiceClient GetBlobServiceClient(string accountName)
{
    BlobServiceClient client = new(
        new Uri($"https://{accountName}.blob.core.windows.net"),
        new DefaultAzureCredential());

    return client;
}

.NET 앱에서 종속성 주입을 위한 서비스 클라이언트를 등록할 수 있습니다.

특정 컨테이너 또는 Blob을 위한 클라이언트 개체도 만들 수 있습니다. 클라이언트 개체 만들기 및 관리에 대한 자세한 내용은 데이터 리소스와 상호 작용하는 클라이언트 개체 만들기 및 관리를 참조하세요.

권한 부여

권한 부여 메커니즘에는 Blob을 업로드하는 데 필요한 권한이 있어야 합니다. Microsoft Entra ID로 권한을 부여하려면(권장) Azure RBAC 기본 제공 역할 Storage Blob 데이터 기여자 이상이 필요합니다. 자세한 내용은 Blob 배치(REST API)블록 배치(REST API)에 대한 권한 부여 지침을 참조하세요.

블록 Blob에 데이터 업로드

다음 메서드를 사용하여 블록 Blob에 데이터를 업로드할 수 있습니다.

이러한 업로드 방법을 사용할 때 클라이언트 라이브러리는 Put Blob을 호출하거나 Put Block List가 뒤따르는 일련의 Put Block 호출을 호출할 수 있습니다. 이 동작은 개체의 전체 크기와 데이터 전송 옵션을 설정한 방법에 따라 달라집니다.

Blob Storage에서 스트림을 연 다음, 해당 스트림에 쓰려면 다음 방법 중 하나를 사용합니다.

로컬 파일 경로에서 블록 Blob 업로드

다음 예에서는 로컬 파일 경로에서 블록 Blob을 업로드합니다.

public static async Task UploadFromFileAsync(
    BlobContainerClient containerClient,
    string localFilePath)
{
    string fileName = Path.GetFileName(localFilePath);
    BlobClient blobClient = containerClient.GetBlobClient(fileName);

    await blobClient.UploadAsync(localFilePath, true);
}

스트림에서 블록 Blob 업로드

다음 예에서는 Stream 개체를 만든 다음, 해당 스트림을 업로드하여 블록 Blob을 업로드합니다.

public static async Task UploadFromStreamAsync(
    BlobContainerClient containerClient,
    string localFilePath)
{
    string fileName = Path.GetFileName(localFilePath);
    BlobClient blobClient = containerClient.GetBlobClient(fileName);

    FileStream fileStream = File.OpenRead(localFilePath);
    await blobClient.UploadAsync(fileStream, true);
    fileStream.Close();
}

BinaryData 개체에서 블록 Blob 업로드

다음 예에서는 BinaryData 개체에서 블록 Blob을 업로드합니다.

public static async Task UploadFromBinaryDataAsync(
    BlobContainerClient containerClient,
    string localFilePath)
{
    string fileName = Path.GetFileName(localFilePath);
    BlobClient blobClient = containerClient.GetBlobClient(fileName);

    FileStream fileStream = File.OpenRead(localFilePath);
    BinaryReader reader = new BinaryReader(fileStream);

    byte[] buffer = new byte[fileStream.Length];
    reader.Read(buffer, 0, buffer.Length);
    BinaryData binaryData = new BinaryData(buffer);

    await blobClient.UploadAsync(binaryData, true);

    fileStream.Close();
}

문자열에서 블록 Blob 업로드

다음 예에서는 문자열에서 블록 Blob을 업로드합니다.

public static async Task UploadFromStringAsync(
    BlobContainerClient containerClient,
    string blobName)
{
    BlobClient blobClient = containerClient.GetBlobClient(blobName);
    string blobContents = "Sample blob data";

    await blobClient.UploadAsync(BinaryData.FromString(blobContents), overwrite: true);
}

Blob Storage의 스트림에 업로드

Blob Storage에서 스트림을 열고 쓸 수 있습니다. 다음 예제에서는 Blob Storage에 zip 파일을 만들고 여기에 파일을 씁니다. 로컬 메모리에 zip 파일을 빌드하는 대신 한 번에 하나의 파일만 메모리에 있습니다.

public static async Task UploadToStreamAsync(
    BlobContainerClient containerClient,
    string localDirectoryPath)
{
    string zipFileName = Path.GetFileName(
        Path.GetDirectoryName(localDirectoryPath)) + ".zip";

    BlockBlobClient blockBlobClient = containerClient.GetBlockBlobClient(zipFileName);

    using (Stream stream = await blockBlobClient.OpenWriteAsync(true))
    {
        using (ZipArchive zip = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: false))
        {
            foreach (var fileName in Directory.EnumerateFiles(localDirectoryPath))
            {
                using (var fileStream = File.OpenRead(fileName))
                {
                    var entry = zip.CreateEntry(
                        Path.GetFileName(fileName), CompressionLevel.Optimal);
                    using (var innerFile = entry.Open())
                    {
                        await fileStream.CopyToAsync(innerFile);
                    }
                }
            }
        }
    }
}

구성 옵션을 사용하여 블록 Blob 업로드

Blob을 업로드할 때 클라이언트 라이브러리 구성 옵션을 정의할 수 있습니다. 이러한 옵션을 조정하여 성능을 개선하고 안정성을 향상시키고 비용을 최적화할 수 있습니다. 다음 코드 예에서는 업로드 메서드를 호출할 때 BlobUploadOptions를 사용하여 구성 옵션을 정의하는 방법을 보여줍니다.

업로드할 때 데이터 전송 옵션 지정

StorageTransferOptions의 값을 구성하여 데이터 전송 작업에 대한 성능을 향상시킬 수 있습니다. 다음 코드 예에서는 StorageTransferOptions에 대한 값을 설정하고 BlobUploadOptions 인스턴스의 일부로 옵션을 포함하는 방법을 보여줍니다. 이 샘플에 제공된 값은 권장 사항이 아닙니다. 이러한 값을 올바르게 조정하려면 앱의 특정 요구 사항을 고려해야 합니다.

public static async Task UploadWithTransferOptionsAsync(
    BlobContainerClient containerClient,
    string localFilePath)
{
    string fileName = Path.GetFileName(localFilePath);
    BlobClient blobClient = containerClient.GetBlobClient(fileName);

    var transferOptions = new StorageTransferOptions
    {
        // Set the maximum number of parallel transfer workers
        MaximumConcurrency = 2,

        // Set the initial transfer length to 8 MiB
        InitialTransferSize = 8 * 1024 * 1024,

        // Set the maximum length of a transfer to 4 MiB
        MaximumTransferSize = 4 * 1024 * 1024
    };

    var uploadOptions = new BlobUploadOptions()
    {
        TransferOptions = transferOptions
    };

    FileStream fileStream = File.OpenRead(localFilePath);
    await blobClient.UploadAsync(fileStream, uploadOptions);
    fileStream.Close();
}

데이터 전송 옵션 튜닝에 대한 자세한 내용은 .NET를 사용하여 업로드 및 다운로드에 대한 성능 조정을 참조하세요.

업로드할 때 전송 유효성 검사 옵션 지정

전송 유효성 검사 옵션을 지정하여 데이터가 제대로 업로드되고 전송 중에 변조되지 않도록 할 수 있습니다. 전송 유효성 검사 옵션은 BlobClientOptions를 사용하여 클라이언트 수준에서 정의할 수 있으며, 이는 유효성 검사 옵션을 BlobClient 인스턴스에서 호출된 모든 메서드에 적용합니다.

또한 BlobUploadOptions를 사용하여 메서드 수준에서 전송 유효성 검사 옵션을 재정의할 수도 있습니다. 다음 코드 예에서는 BlobUploadOptions 개체를 만들고 체크섬을 생성하기 위한 알고리즘을 지정하는 방법을 보여줍니다. 그런 다음, 서비스에서 체크섬을 사용하여 업로드한 콘텐츠의 데이터 무결성을 확인합니다.

public static async Task UploadWithChecksumAsync(
    BlobContainerClient containerClient,
    string localFilePath)
{
    string fileName = Path.GetFileName(localFilePath);
    BlobClient blobClient = containerClient.GetBlobClient(fileName);

    var validationOptions = new UploadTransferValidationOptions
    {
        ChecksumAlgorithm = StorageChecksumAlgorithm.Auto
    };

    var uploadOptions = new BlobUploadOptions()
    {
        TransferValidation = validationOptions
    };

    FileStream fileStream = File.OpenRead(localFilePath);
    await blobClient.UploadAsync(fileStream, uploadOptions);
    fileStream.Close();
}

다음 표에서는 StorageChecksumAlgorithm으로 정의된 대로, 체크섬 알고리즘에 사용할 수 있는 옵션을 보여줍니다.

속성 설명
자동 0 권장. 라이브러리에서 알고리즘 선택을 허용합니다. 다른 라이브러리 버전은 다른 알고리즘을 선택할 수 있습니다.
없음 1 선택한 알고리즘이 없습니다. 체크섬을 계산하거나 요청하지 마세요.
MD5 2 표준 MD5 해시 알고리즘.
StorageCrc64 3 Azure Storage 사용자 지정 64비트 CRC.

참고 항목

요청에 지정된 체크섬이 서비스에서 계산한 체크섬과 일치하지 않으면 업로드 작업이 실패합니다. 기본 다시 시도 정책을 사용하는 경우 작업이 다시 시도되지 않습니다. .NET에서 RequestFailedException은 사용되는 알고리즘에 따라 상태 코드 400 및 오류 코드 Md5Mismatch 또는 Crc64Mismatch로 throw됩니다.

인덱스 태그로 업로드

Blob 인덱스 태그는 키-값 태그 특성을 사용하여 스토리지 계정의 데이터를 분류합니다. 이러한 태그는 데이터를 쉽게 찾을 수 있도록 검색 가능한 다차원 인덱스로 자동으로 인덱싱되고 표시됩니다. BlobUploadOptions 인스턴스에 태그를 추가하고 해당 인스턴스를 UploadAsync 메서드에 전달할 수 있습니다.

다음 예제에서는 인덱스 태그가 있는 블록 Blob을 업로드합니다.

public static async Task UploadBlobWithTagsAsync(
    BlobContainerClient containerClient,
    string blobName)
{
    BlobClient blobClient = containerClient.GetBlobClient(blobName);
    string blobContents = "Sample blob data";

    BlobUploadOptions options = new BlobUploadOptions();
    options.Tags = new Dictionary<string, string>
    {
        { "Sealed", "false" },
        { "Content", "image" },
        { "Date", "2020-04-20" }
    };

    await blobClient.UploadAsync(BinaryData.FromString(blobContents), options);
}

업로드 시 Blob의 액세스 계층 설정

BlobUploadOptions 클래스를 사용하여 업로드 시 Blob의 액세스 계층을 설정할 수 있습니다. 다음 코드 예에서는 Blob을 업로드할 때 액세스 계층을 설정하는 방법을 보여줍니다.

public static async Task UploadWithAccessTierAsync(
    BlobContainerClient containerClient,
    string localFilePath)
{
    string fileName = Path.GetFileName(localFilePath);
    BlockBlobClient blockBlobClient = containerClient.GetBlockBlobClient(fileName);

    var uploadOptions = new BlobUploadOptions()
    {
        AccessTier = AccessTier.Cool
    };

    FileStream fileStream = File.OpenRead(localFilePath);
    await blockBlobClient.UploadAsync(fileStream, uploadOptions);
    fileStream.Close();
}

액세스 계층 설정은 블록 Blob에서만 허용됩니다. 블록 Blob에 대한 액세스 계층을 Hot, Cool, Cold 또는 Archive로 설정할 수 있습니다. 액세스 계층을 Cold로 설정하려면 최소 클라이언트 라이브러리 버전, 12.15.0을 사용해야 합니다.

액세스 계층에 대한 자세한 내용은 액세스 계층 개요를 참조하세요.

블록을 준비하고 커밋하여 블록 Blob 업로드

개별 데이터 블록을 수동으로 스테이징하여 업로드를 블록으로 나누는 방법을 보다 효율적으로 제어할 수 있습니다. Blob을 구성하는 모든 블록이 준비되면 Blob Storage에 커밋할 수 있습니다. 이 접근방식을 사용하여 블록을 병렬로 업로드하여 성능을 향상시킬 수 있습니다.

public static async Task UploadBlocksAsync(
    BlobContainerClient blobContainerClient,
    string localFilePath,
    int blockSize)
{
    string fileName = Path.GetFileName(localFilePath);
    BlockBlobClient blobClient = blobContainerClient.GetBlockBlobClient(fileName);

    FileStream fileStream = File.OpenRead(localFilePath);
    ArrayList blockIDArrayList = new ArrayList();
    byte[] buffer;

    var bytesLeft = (fileStream.Length - fileStream.Position);

    while (bytesLeft > 0)
    {
        if (bytesLeft >= blockSize)
        {
            buffer = new byte[blockSize];
            await fileStream.ReadAsync(buffer, 0, blockSize);
        }
        else
        {
            buffer = new byte[bytesLeft];
            await fileStream.ReadAsync(buffer, 0, Convert.ToInt32(bytesLeft));
            bytesLeft = (fileStream.Length - fileStream.Position);
        }

        using (var stream = new MemoryStream(buffer))
        {
            string blockID = Convert.ToBase64String(
                Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));

            blockIDArrayList.Add(blockID);
            await blobClient.StageBlockAsync(blockID, stream);
        }
        bytesLeft = (fileStream.Length - fileStream.Position);
    }

    string[] blockIDArray = (string[])blockIDArrayList.ToArray(typeof(string));

    await blobClient.CommitBlockListAsync(blockIDArray);
}

리소스

.NET용 Azure Blob Storage 클라이언트 라이브러리를 사용하여 Blob을 업로드하는 방법에 대한 자세한 내용은 다음 리소스를 참조하세요.

코드 샘플

REST API 작업

.NET용 Azure SDK에는 Azure REST API를 기반으로 빌드되는 라이브러리가 포함되어 있으므로 익숙한 .NET 패러다임을 통해 REST API 작업과 상호 작용할 수 있습니다. Blob을 업로드하기 위한 클라이언트 라이브러리 메서드는 다음 REST API 작업을 사용합니다.

참고 항목

  • 이 문서는 .NET용 Blob Storage 개발자 가이드의 일부입니다. 자세한 내용은 .NET 앱 빌드에서 개발자 가이드 문서의 전체 목록을 참조하세요.