Exercício – carregar recursos para serem utilizados por um Batch com a biblioteca de armazenamento .NET

Concluído

Importante

Precisa da sua própria subscrição do Azure para executar este exercício e poderá incorrer em custos. Se ainda não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar.

A biblioteca do Armazenamento do Azure permite-lhe controlar de forma programática o armazenamento de ficheiros numa conta de Armazenamento do Azure.

Neste exercício, vamos melhorar a nossa aplicação para carregar vídeos para o armazenamento de blobs.

Adicionar detalhes da ligação da conta de armazenamento

  1. No Cloud Shell, adicione o pacote NuGet de armazenamento de Blob do Azure:

    dotnet add package Microsoft.Azure.Storage.Blob
    
  2. Edite o ficheiro Program.cs no editor:

    code Program.cs
    
  3. Adicione as seguintes instruções using à parte superior do Program.cs para incluir as bibliotecas de que nosso trabalho de armazenamento precisa:

    using Microsoft.Azure.Storage.Blob;
    using Microsoft.Azure.Storage;
    using System.IO;
    

    Microsoft.Azure.Storage.Blob e Microsoft.Azure.Storage dão à aplicação acesso à conta de Armazenamento do Azure. System.IO dá à aplicação acesso ao sistema de ficheiros para processamento de ficheiros.

  4. Adicione variáveis para as credenciais de Armazenamento do Program Azure à classe em Program.cs:

    // Storage account credentials
    private const string envVarStorage = "STORAGE_NAME";
    private const string envVarStorageKey = "STORAGE_KEY";
    private static string storageAccountName;
    private static string storageAccountKey;
    

Criar um contentor de entrada e saída

  1. Substitua Main() no Program.cs pela seguinte atualização, que adiciona código para gerenciar a conta de armazenamento:

    static async Task Main(string[] args)
    {
        // Read the environment variables to allow the app to connect to the Azure Batch and Azure Storage accounts
        batchAccountUrl = Environment.GetEnvironmentVariable(envVarBatchURI);
        batchAccountName = Environment.GetEnvironmentVariable(envVarBatchName);
        batchAccountKey = Environment.GetEnvironmentVariable(envVarKey);
        storageAccountName = Environment.GetEnvironmentVariable(envVarStorage);
        storageAccountKey = Environment.GetEnvironmentVariable(envVarStorageKey);
    
        // Show the user the accounts they are attaching to
        Console.WriteLine("BATCH URL: {0}, Name: {1}, Key: {2}", batchAccountUrl, batchAccountName, batchAccountKey);
        Console.WriteLine("Storage Name: {0}, Key: {1}", storageAccountName, storageAccountKey);
    
        // Construct the Storage account connection string
        string storageConnectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                            storageAccountName, storageAccountKey);
    
        // Retrieve the storage account
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
    
        // Create the blob client, for use in obtaining references to blob storage containers
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    
        // Use the blob client to create the containers in blob storage
        const string inputContainerName = "input";
        const string outputContainerName = "output";
    
        await CreateContainerIfNotExistAsync(blobClient, inputContainerName);
        await CreateContainerIfNotExistAsync(blobClient, outputContainerName);
    
        // RESOURCE FILE SETUP
        // Add *.mp4 files into the \<solutiondir>\InputFiles folder.
    
        string inputPath = Path.Combine(Environment.CurrentDirectory, "InputFiles");
        List<string> inputFilePaths = new List<string>(
            Directory.GetFileSystemEntries(inputPath, "*.mp4", SearchOption.TopDirectoryOnly));
    
        // Upload data files.
        // Upload the data files using UploadResourceFilesToContainer(). This data will be
        // processed by each of the tasks that are executed on the compute nodes within the pool.
        List<ResourceFile> inputFiles = await UploadFilesToContainerAsync(blobClient, inputContainerName, inputFilePaths);
    
        // Obtain a shared access signature that provides write access to the output container to which
        // the tasks will upload their output.
        string outputContainerSasUrl = GetContainerSasUrl(blobClient, outputContainerName, SharedAccessBlobPermissions.Write);
    
        // The batch client requires a BatchSharedKeyCredentials object to open a connection
        var sharedKeyCredentials = new BatchSharedKeyCredentials(batchAccountUrl, batchAccountName, batchAccountKey);
        var batchClient = BatchClient.Open(sharedKeyCredentials);
    
        // Create the Batch pool, which contains the compute nodes that execute tasks.
        await CreateBatchPoolAsync(batchClient, PoolId);
    }
    

    No código anterior, um CloudStorageAccount objeto é criado para permitir que o aplicativo crie um cliente de blob. O cliente é utilizado para criar os contentores de armazenamento, carregar os ficheiros e dar acesso ao trabalho para escrever no contentor de saída.

Criar contentores de armazenamento para a entrada e saída de ficheiros

  1. Adicione o seguinte método, CreateContainerIfNotExistAsync(), para criar um contêiner com o nome próprio:

    private static async Task CreateContainerIfNotExistAsync(CloudBlobClient blobClient, string containerName)
    {
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        await container.CreateIfNotExistsAsync();
        Console.WriteLine("Creating container [{0}].", containerName);
    }
    

    O código anterior usa o CloudBlobClient criado no Main método para criar contêineres.

Processar a lista de todos os ficheiros a carregar

  1. Adicione o seguinte método, UploadFilesToContainerAsync(), para carregar uma lista de arquivos de entrada para o contêiner:

    private static async Task<List<ResourceFile>> UploadFilesToContainerAsync(CloudBlobClient blobClient, string inputContainerName, List<string> filePaths)
    {
        List<ResourceFile> resourceFiles = new List<ResourceFile>();
    
        foreach (string filePath in filePaths)
        {
            resourceFiles.Add(await UploadResourceFileToContainerAsync(blobClient, inputContainerName, filePath));
        }
    
        return resourceFiles;
    }
    

    O código anterior usa a lista criada de caminhos de arquivo para chamar um método para carregá-los e armazenar a referência ResourceFile produzida para uso pelo trabalho em lote.

Carregar os ficheiros

  1. Adicione um método para carregar os arquivos locais no armazenamento do Azure:

    private static async Task<ResourceFile> UploadResourceFileToContainerAsync(CloudBlobClient blobClient, string containerName, string filePath)
    {
        Console.WriteLine("Uploading file {0} to container [{1}]...", filePath, containerName);
    
        string blobName = Path.GetFileName(filePath);
        var fileStream = System.IO.File.OpenRead(filePath);
    
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        CloudBlockBlob blobData = container.GetBlockBlobReference(blobName);
        await blobData.UploadFromFileAsync(filePath);
    
        // Set the expiry time and permissions for the blob shared access signature. In this case, no start time is specified,
        // so the shared access signature becomes valid immediately
        SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(2),
            Permissions = SharedAccessBlobPermissions.Read
        };
    
        // Construct the SAS URL for the blob
        string sasBlobToken = blobData.GetSharedAccessSignature(sasConstraints);
        string blobSasUri = String.Format("{0}{1}", blobData.Uri, sasBlobToken);
    
        return ResourceFile.FromUrl(blobSasUri, blobName);
    }
    

    O código anterior usa o para carregar os arquivos de forma assíncrona CloudBlobClient . Ele cria um arquivo de recurso que é adicionado a uma lista que a tarefa adicionada no próximo exercício usará.

Ativar o acesso à pasta de saída

  1. Crie uma referência SAS (Assinatura de Acesso Compartilhado) ao contêiner de saída para tarefas para gravar seus arquivos em:

    private static string GetContainerSasUrl(CloudBlobClient blobClient, string containerName, SharedAccessBlobPermissions permissions)
    {
        // Set the expiry time and permissions for the container access signature. In this case, no start time is specified,
        // so the shared access signature becomes valid immediately. Expiration is in 2 hours.
        SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(2),
            Permissions = permissions
        };
    
        // Generate the shared access signature on the container, setting the constraints directly on the signature
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);
    
        // Return the URL string for the container, including the SAS token
        return String.Format("{0}{1}", container.Uri, sasContainerToken);
    }
    

    O código anterior cria um URL SAS com acesso limitado (duas horas) para a tarefa para permitir que ela escreva os GIFs animados convertidos no armazenamento de Blob.

  2. No editor de códigos, clique com o botão direito do mouse e selecione Salvar, clique com o botão direito do mouse e selecione Sair.

Testar os carregamentos de ficheiros

  1. No Cloud Shell, crie uma pasta InputFiles no diretório do aplicativo:

    mkdir InputFiles
    
  2. Execute os seguintes comandos curl no Cloud Shell para copiar um conjunto de exemplo de vídeos de animais do repositório GitHub do módulo para a pasta InputFiles local.

    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/1.mp4 > ./InputFiles/1.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/2.mp4 > ./InputFiles/2.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/3.mp4 > ./InputFiles/3.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/4.mp4 > ./InputFiles/4.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/5.mp4 > ./InputFiles/5.mp4
    curl -L https://github.com/MicrosoftDocs/mslearn-apps-and-batch/raw/master/cutifypets/InputFiles/6.mp4 > ./InputFiles/6.mp4
    
  3. Guarde as credenciais do Armazenamento do Azure em variáveis de ambiente. O segundo comando consiste em utilizar a variável de ambiente RESOURCE_GROUP que definimos na secção Configurar detalhes de ligação da aplicação do exercício anterior, Exercício – aceder à conta do Batch com a biblioteca de cliente do .NET. O valor é o nome do grupo de recursos que você selecionou quando criou sua conta de lote.

    export STORAGE_NAME=$(az storage account list --query "[?contains(name,'cuti')].name" --output tsv)
    export STORAGE_KEY=$(az storage account keys list --account-name $STORAGE_NAME --query [0].value --output tsv --resource-group $RESOURCE_GROUP)
    
  4. Crie e execute o aplicativo:

    dotnet run
    
  5. O programa deve executar e escrever as seguintes mensagens no terminal:

    BATCH URL: [your batch url], Name: [your batch account name], Key: [your batch key]
    Storage Name: [your storage account name], Key: [your storage key]
    Creating container [input].
    Creating container [output].
    Uploading file ~\cutifypets\InputFiles\3.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\2.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\4.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\1.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\5.mp4 to container [input]...
    Uploading file ~\cutifypets\InputFiles\6.mp4 to container [input]...
    Creating pool [WinFFmpegPool]...
    

Verificar os ficheiros carregados com o portal do Azure

  1. Regresse ao portal do Azure. No menu à esquerda, selecione Contas de armazenamento e, em seguida, selecione a conta de armazenamento criada no primeiro exercício.

    Screenshot that shows a user's storage accounts.

  2. No menu à esquerda, selecione Contêineres em Armazenamento de dados e, em seguida, selecione a pasta de entrada.

    Screenshot that shows the created containers in blob storage.

  3. A pasta contém os vídeos carregados.

    Screenshot that shows the uploaded video files.