A Microsoft está em fase Alpha com o Azure mesmo. Testando os blobs, todo o processamento passa por um projeto que eles criaram chamado “StorageClient”, que faz parte do SDK. Imagino que até o lançamento, na verdade, espero que em um CTP futuro, já tenhamos um conjunto de bibliotecas mais padronizado.

De qualquer maneira, sigo fazendo vários testes, e posso dizer para vocês que o Blog Storage funciona perfeitamente. A API é bem simples. Os blobs no Azure são conteúdos binários, e são usados para armazenar qualquer arquivo que você quiser. Podem ser músicas, imagens, zips, o que você quiser.

Por exemplo, para criar o objeto de contêiner, você faz assim:

        private BlobContainer container;

        private BlobContainer GetContainer()
        {
            BlobStorage blobStorage = BlobStorage.Create(StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration());
            BlobContainer newContainer = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));

            newContainer.CreateContainer(null, ContainerAccessControl.Public);
            return newContainer;
        }

Muito simples, certo? Daí para obter os blobs do contêiner, chama um “ListBlobs”, assim:

        private void RefreshGallery()
        {
          this.images.DataSource = this.container.ListBlobs(String.Empty, false);
          this.images.DataBind();
        }

Para apagar um blog é simples também:

                string blobName = (string)e.CommandArgument;
                if (this.container.DoesBlobExist(blobName))
                {
                    this.container.DeleteBlob(blobName);
                }

Para criar um blob, você pega um arquivo postado e uma strings de uns textboxes, e manda para o serviço, o arquivo como conteúdo, e o resto como metadados. A API continua muito simples (dei uma resumida):

 private void SaveImage(string id, string fileName, string contentType, byte[] data)
        {
            BlobProperties properties = 
                new BlobProperties(string.Format(CultureInfo.InvariantCulture, "image_{0}", id));
            NameValueCollection metadata = new NameValueCollection();
            metadata["Id"] = id;
            metadata["Filename"] = fileName;
            properties.Metadata = metadata;
            properties.ContentType = contentType;
            BlobContents imageBlob = new BlobContents(data);
            this.container.CreateBlob(properties, imageBlob, true);
        }

Subi algumas imagens. Os resultado é uma página web que fica simples, mas funciona:

Resultado dos testes

Se você for olhar na URL da imagem, vai ver que ela vem do serviço de blogs:

Imagem no Azure Blobs

Testei com arquivos grandes, e ele quebra o blob em vários “blocks”, para permitir reenvio em caso de quebra de conexão, e não precisar reenviar o arquivo inteiro. Inteligente. Isso está no método PutBlobImpl, que reproduzo abaixo:

        private bool PutBlobImpl(BlobProperties blobProperties, Stream stream, bool overwrite, string eTag)
        {
            // If the blob is large, we should use blocks to upload it in pieces.
            // This will ensure that a broken connection will only impact a single piece
            long originalPosition = stream.Position;
            long length = stream.Length - stream.Position;
            if (length > ChunkingSize)
                return PutLargeBlobImpl(blobProperties, stream, overwrite, eTag);

            bool retval = false;
            RetryPolicy R = stream.CanSeek ? this.RetryPolicy : RetryPolicies.NoRetry;
            R(() =>
            {
                if (stream.CanSeek)
                    stream.Position = originalPosition;
                retval = UploadData(blobProperties, stream, length, overwrite, eTag, new NameValueCollection());
            });

            return retval;
        }

Viram também o sistema de retries, todo baseado em delegates e lambdas? Elegante, não?

Infelizmente os metadados não funcionam ainda com caracteres fora do ANSI, como acentos, cedilha, etc. Mas funcionam direito se você evitá-los.

Todos esses exemplos estão no Trainning Kit de Fevereiro, que você pega aqui. O material é bem legal e muito claro e direto.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.