Exportar (0) Imprimir
Expandir Tudo

Ingestão de ativos em massa com a API REST

Atualizado: agosto de 2014

A ingestão de ativos em massa ou "ingestão em massa" envolve separar a criação do ativo do processo de carregamento. O motivo disso é que o carregamento de grandes arquivos de ativo causa um afunilamento na criação de ativos. Ao usar a abordagem de ingestão em massa, você cria um manifesto (IngestManifest) que descreve o ativo e os seus arquivos associados. Em seguida, use o método de carregamento de sua escolha para carregar os arquivos associados no contêiner blob do manifesto. OServiços de Mídia do Microsoft Azure observa o contêiner blob associado ao manifesto aguardando pelos carregamentos dos arquivos. Uma vez que o arquivo é carregado no contêiner blob, o Serviços de Mídia do Microsoft Azure conclui a criação do ativo com base na configuração do ativo no manifesto (IngestManifestAsset).

Este tópico descreve a ingestão de ativos em massa usando a API REST. Para obter mais informações sobre a ingestão de ativos em massa usando o SDK do Serviços de Mídia do Microsoft Azure, consulte Ingerir ativos em massa com o SDK do Media Services para .NET. Para obter mais informações sobre a ingestão de ativos, consulte Ingestão de Ativos com o API REST de Serviços de Mídia.

O fluxo de trabalho básico para a ingestão em massa é dividido nas seguintes seções:

ImportantImportante
Ao trabalhar com os Serviços de Mídia do API REST, as seguintes considerações se aplicam:

noteObservação
O Media Services utiliza o valor da propriedade IAssetFile.Name ao criar URLs para o conteúdo de streaming (por exemplo, http://{WAMSAccount}.origin.mediaservices.windows.net/{GUID}/{IAssetFile.Name}/streamingParameters.) Por esse motivo, a codificação por percentual não é permitida. O valor da propriedade Name não pode conter qualquer um dos seguintes caracteres reservados codificados por percentual: !*'();:@&=+$,/?%#[]". Além disso, pode somente haver um ‘.’ para cada extensão de nome de arquivo.

O IngestManifest é um contêiner para um conjunto de ativos, arquivos de ativos e informações estatísticas que podem ser usadas para determinar o progresso da ingestão em massa para o conjunto.

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

POST https:// media.windows.net/API/IngestManifests HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net
Content-Length: 36
Expect: 100-continue

{ "Name" : "ExampleManifestREST" }

Antes de criar o IngestManifestAsset, você precisa criar o ativo que será concluído usando a ingestão em massa. Um ativo é um contêiner para múltiplos tipos ou conjuntos de objetos no Media Services, incluindo vídeo, áudio, imagens, coleções de miniaturas, faixas de texto e arquivos de legenda codificada. Na API REST, criar um ativo requer o envio de uma solicitação HTTP POST para Serviços de Mídia do Microsoft Azure e o fornecimento de qualquer informação de propriedade sobre o ativo no corpo da solicitação. Neste exemplo, o ativo é criado usando a opção StorageEncryption(1) incluída no corpo da solicitação.

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

POST https://media.windows.net/API/Assets HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net
Content-Length: 55
Expect: 100-continue

{ "Name" : "ExampleManifestREST_Asset", "Options" : 1 }

Os IngestManifestAssets representam os ativos em um IngestManifest que são usados com a ingestão em massa. Isso basicamente conecta o ativo ao manifesto. Serviços de Mídia do Microsoft Azure observa internamente o upload do arquivo com base na coleção IngestManifestFiles associada ao IngestManifestAsset. Assim que esses arquivos são carregados, o ativo é concluído. É possível criar um novo IngestManifestAsset com uma solicitação HTTP POST. No corpo da solicitação, inclua a ID do IngestManifest e a ID do ativo que o IngestManifestAsset deve vincular para a ingestão em massa.

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

POST https://media.windows.net/API/IngestManifestAssets HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net
Content-Length: 152
Expect: 100-continue
{ "ParentIngestManifestId" : "nb:mid:UUID:5c77f186-414f-8b48-8231-17f9264e2048", "Asset" : { "Id" : "nb:cid:UUID:b757929a-5a57-430b-b33e-c05c6cbef02e"}}

Se o ativo for usar criptografia, você deverá criar o ContentKey para ser usado na criptografia antes de criar os IngestManifestFiles para o ativo. Caso não seja necessário usar criptografia, será possível ignorar esta seção. Uma vez que usamos StorageEncryption no ativo de exemplo criado acima, vamos demonstrar a criação de um ContentKey para o ativo. Para criar um novo ContentKey para o ativo, enviamos uma solicitação HTTP POST. As propriedades a seguir são incluídas no corpo da solicitação.

 

Propriedade do corpo da solicitação Descrição

Id

A ID de ContentKey que nós mesmos geramos usando o seguinte formato, "nb:kid:UUID:<NOVA GUID>".

ContentKeyType

Esse é o tipo de chave de conteúdo como um inteiro para esta chave de conteúdo. Passamos o valor 1 para criptografia de armazenamento.

EncryptedContentKey

Criamos um novo valor de chave de conteúdo que é um valor de 256 bits (32 bytes). A chave é criptografada usando o certificado X.509 de criptografia de armazenamento que recuperamos de Serviços de Mídia do Microsoft Azure executando uma solicitação HTTP GET para os métodos GetProtectionKeyId e GetProtectionKey.

ProtectionKeyId

Essa é a ID da chave de proteção para o certificado X.509 de criptografia de armazenamento que foi usada para criptografar a chave de conteúdo.

ProtectionKeyType

Esse é o tipo de criptografia para a chave de proteção que foi usada para criptografar a chave de conteúdo. Neste exemplo, o valor é StorageEncryption(1).

Checksum

A soma de verificação calculada MD5 para a chave de conteúdo. Ela é calculada criptografando a ID do conteúdo com a chave de conteúdo. O código de exemplo demonstra como calcular a soma de verificação.

Para obter mais detalhes sobre a criptografia de ativos com o certificado x.509, consulte Criptografar o ativo (opcional).

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

POST https://media.windows.net/api/ContentKeys HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net
Content-Length: 572
Expect: 100-continue

{"Id" : "nb:kid:UUID:316d14d4-b603-4d90-b8db-0fede8aa48f8", "ContentKeyType" : 1, "EncryptedContentKey" : "Y4NPej7heOFa2vsd8ZEOcjjpu/qOq3RJ6GRfxa8CCwtAM83d6J2mKOeQFUmMyVXUSsBCCOdufmieTKi+hOUtNAbyNM4lY4AXI537b9GaY8oSeje0NGU8+QCOuf7jGdRac5B9uIk7WwD76RAJnqyep6U/OdvQV4RLvvZ9w7nO4bY8RHaUaLxC2u4aIRRaZtLu5rm8GKBPy87OzQVXNgnLM01I8s3Z4wJ3i7jXqkknDy4VkIyLBSQvIvUzxYHeNdMVWDmS+jPN9ScVmolUwGzH1A23td8UWFHOjTjXHLjNm5Yq+7MIOoaxeMlKPYXRFKofRY8Qh5o5tqvycSAJ9KUqfg==", "ProtectionKeyId" : "7D9BB04D9D0A4A24800CADBFEF232689E048F69C", "ProtectionKeyType" : 1, "Checksum" : "TfXtjCIlq1Y=" }

O ContentKey é associado a um ou mais ativos enviando uma solicitação HTTP POST. A solicitação a seguir é um exemplo para vincular o ContentKey de exemplo ao ativo de exemplo pela ID.

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

POST https://media.windows.net/API/Assets('nb:cid:UUID:b3023475-09b4-4647-9d6d-6fc242822e68')/$links/ContentKeys HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net
Content-Length: 113
Expect: 100-continue

{ "uri": "https://media.windows.net/api/ContentKeys('nb%3Akid%3AUUID%3A32e6efaf-5fba-4538-b115-9d1cefe43510')"}

Um IngestManifestFile representa um objeto blob de vídeo ou de áudio que será carregado como parte da ingestão em massa para um ativo. As propriedades relacionadas à criptografia não são necessárias, a menos que o ativo esteja usando uma opção de criptografia. O exemplo usado nesta seção demonstra a criação de um IngestManifestFile que usa StorageEncryption para o ativo criado anteriormente.

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

 POST https://media.windows.net/API/IngestManifestFiles HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net
Content-Length: 367
Expect: 100-continue

{ "Name" : "REST_Example_File.wmv", "ParentIngestManifestId" : "nb:mid:UUID:5c77f186-414f-8b48-8231-17f9264e2048", "ParentIngestManifestAssetId" : "nb:maid:UUID:beed8531-9a03-9043-b1d8-6a6d1044cdda", "IsEncrypted" : "true", "EncryptionScheme" : "StorageEncryption", "EncryptionVersion" : "1.0", "EncryptionKeyId" : "nb:kid:UUID:32e6efaf-5fba-4538-b115-9d1cefe43510" }

É possível usar qualquer aplicativo cliente de alta velocidade capaz de carregar os arquivos de ativo para o URI do contêiner de armazenamento blob fornecido pela propriedade BlobStorageUriForUpload do IngestManifest. Um notável serviço de carregamento de alta velocidade é o Aspera On Demand for Azure Application.

É possível monitorar o progresso de operações de ingestão em massa para um IngestManifest sondando a propriedade Statistics do IngestManifest. Essa propriedade é um tipo complexo, IngestManifestStatistics. Para sondar a propriedade Statistics, envie uma solicitação HTTP GET passando a ID do IngestManifest

A solicitação de exemplo a seguir foi gerada com o Código de Exemplo fornecido no final deste tópico.

GET https://media.windows.net/API/IngestManifests('nb:mid:UUID:5c77f186-414f-8b48-8231-17f9264e2048') HTTP/1.1
Content-Type: application/json;odata=verbose
Accept: application/json;odata=verbose
DataServiceVersion: 3.0
MaxDataServiceVersion: 3.0
x-ms-version: 2.5
Authorization: Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=070500D0-F35C-4A5A-9249-485BBF4EC70B&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1334275521&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=GxdBb%2fmEyN7iHdNxbawawHRftLhPFFqxX1JZckuv3hY%3d
Host: media.windows.net

Este código de exemplo requer referências para os assemblies a seguir. A estrutura de destino está definida como .NET Framework 4 nas configurações do projeto.

  • System.Runtime.Serialization

  • System.Web

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Runtime.Serialization.Json;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace Microsoft.Samples.RestBulkIngest
{
  class Program
  {

    private static Uri serviceURI = new Uri("https://media.windows.net/API/");
    private static readonly string accessControlURI = "https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13";
    private static readonly string clientSecret = ""; // Fill in your client secret/passcode here.
    private static readonly string clientId = ""; // Fill in your client ID here
    private static readonly string scope = "WindowsAzureMediaServices";

    private static string token = null;


    static void Main(string[] args)
    {
      //===[ Retrieves an ACS token ]=============================================================//
      token = GetACSToken(accessControlURI, clientId, clientSecret, scope);

      //===[ Create a named IngestManifest ]======================================================//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("========[ CREATE BULK INGEST MANIFEST ]========");
      Console.WriteLine("===============================================");
      XmlDocument xmlManifestDoc = CreateIngestManifest("ExampleManifestREST");
      string manifestId = xmlManifestDoc.GetElementsByTagName("Id")[0].InnerText;


      //===[ Create an StorageEncryption Asset for bulk ingesting ]===============================//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("================[ CREATE ASSET ]===============");
      Console.WriteLine("===============================================");
      XmlDocument assetXmlResponse = CreateAsset("ExampleManifestREST_Asset", "1");
      string assetId = assetXmlResponse.GetElementsByTagName("Id")[0].InnerText;


      //===[ Create an IngestManifestAsset to link the asset to the manifest ]====================//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("=======[ CREATE INGEST MANIFEST ASSET ]========");
      Console.WriteLine("===============================================");
      XmlDocument xmlManifestAssetDoc = CreateIngestManifestAsset(manifestId, assetId);
      string manifestAssetId = xmlManifestAssetDoc.GetElementsByTagName("Id")[0].InnerText;


      //===[ Create a ContentKey for encryption ]==================================================//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("============[ CREATE CONTENT KEY ]=============");
      Console.WriteLine("===============================================");
      int storageEncryptionType = 1;
      XmlDocument xmlContentKey = CreateContentKey(storageEncryptionType);
      string contentKeyId = xmlContentKey.GetElementsByTagName("Id")[0].InnerText;


      //===[ Link the ContentKey to the Asset for encryption ]=====================================//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("==========[ LINK CONTENTKET TO ASSET ]=========");
      Console.WriteLine("===============================================");
      LinkContentKeyToAsset(assetId, xmlContentKey.GetElementsByTagName("uri")[0].InnerText);


      //===[ Create the IngestManifestFile so that Azure Media Service knows what ]========//
      //===[ files to look for in the blob container associated to the manifest.          ]========//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("========[ CREATE INGEST MANIFEST FILE ]========");
      Console.WriteLine("===============================================");
      CreateIngestManifestFile(manifestId, manifestAssetId, "REST_Example_File.wmv", contentKeyId);


      //===[ Poll the IngestManifest Statistics property for bulk ingress progress ]===============//
      Console.WriteLine("\n===============================================");
      Console.WriteLine("======[ POLL INGEST MANIFEST STATISTICS ]======");
      Console.WriteLine("===============================================");
      PollIngestManifestStatisticsToCompletion(manifestId);
    }



    private static string GetACSToken(string accessControlUri, string clientId, string clientSecret, string scope)
    {
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(accessControlUri);
      request.Method = "POST";
      request.ContentType = "application/x-www-form-urlencoded";
      request.KeepAlive = true;
      string token = null;

      //Note: You need to insert your client Id and secret into this string in order for it to work.
      var requestBytes = Encoding.ASCII.GetBytes("grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + HttpUtility.UrlEncode(clientSecret) + "&scope=urn%3a" + scope);
      request.ContentLength = requestBytes.Length;

      var requestStream = request.GetRequestStream();
      requestStream.Write(requestBytes, 0, requestBytes.Length);
      requestStream.Close();

      var response = (HttpWebResponse)request.GetResponse();

      if (response.StatusCode == HttpStatusCode.OK)
      {
        using (Stream responseStream = response.GetResponseStream())
        {
          using (StreamReader stream = new StreamReader(responseStream))
          {
            string responseString = stream.ReadToEnd();
            var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(responseString), new XmlDictionaryReaderQuotas());

            while (reader.Read())
            {
              if ((reader.Name == "access_token") && (reader.NodeType == XmlNodeType.Element))
              {
                if (reader.Read())
                {
                  token = reader.Value;
                  break;
                }
              }
            }
          }
        }
      }

      return token;
    }



    private static XmlDocument GenerateRequestAndGetResponse(string verb, string resourcePath, string query, string requestbody)
    {
      var uriBuilder = new UriBuilder(serviceURI);
      uriBuilder.Path += resourcePath;
      if (query != null)
      {
        uriBuilder.Query = query;
      }
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uriBuilder.Uri);
      request.Method = verb;
      request.AllowAutoRedirect = false;

      if (resourcePath == "$metadata")
        request.MediaType = "application/xml";
      else
      {
        request.ContentType = "application/json;odata=verbose";
        request.Accept = "application/json;odata=verbose";
      }

      // Uncomment when Media Services supports the JSON OData light.
      //request.ContentType = "application/json;odata=light";
      //request.Accept = "application/json;odata=light";

      request.Headers.Add("DataServiceVersion", "3.0");
      request.Headers.Add("MaxDataServiceVersion", "3.0");
      request.Headers.Add("x-ms-version", "2.5");
      request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);

      if (requestbody != null)
      {
        var requestBytes = Encoding.ASCII.GetBytes(requestbody);
        request.ContentLength = requestBytes.Length;

        var requestStream = request.GetRequestStream();
        requestStream.Write(requestBytes, 0, requestBytes.Length);
        requestStream.Close();
      }
      else
      {
        request.ContentLength = 0;
      }

      XmlDocument xmlResponse = null;

      try
      {
        // Generate HTTP request and pass in JSON defining the Asset's name.    
        var response = (HttpWebResponse)request.GetResponse();

        //TODO: Put in retry logic if token has expired.
        switch (response.StatusCode)
        {
          case HttpStatusCode.MovedPermanently:
            serviceURI = new Uri(response.Headers["Location"]);
            xmlResponse = GenerateRequestAndGetResponse(verb, resourcePath, query, requestbody);
            break;
          case HttpStatusCode.Created:
          case HttpStatusCode.OK:
            using (Stream responseStream = response.GetResponseStream())
            {
              using (StreamReader stream = new StreamReader(responseStream))
              {
                string responseString = stream.ReadToEnd();
                var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(responseString), new XmlDictionaryReaderQuotas());

                xmlResponse = new XmlDocument();
                reader.Read();
                xmlResponse.LoadXml(reader.ReadInnerXml());
              }
            }
            break;

          default:
            Console.WriteLine(response.StatusDescription);
            break;
        }
      }
      catch (WebException ex)
      {
        Console.WriteLine(ex.Message);
      }

      return xmlResponse;
    }


    private static XmlDocument CreateAsset(string name, string options = null)
    {
      XmlDocument assetXmlResponse = null;

      string requestbody;

      if (options != null)
      {
        requestbody = "{ \"Name\" : \"" + name + "\", \"Options\" : " + options + " }";
      }
      else
      {
        requestbody = "{ \"Name\" : \"" + name + "\" }";
      }


      // Generate HTTP request and pass in JSON defining the Asset's name.    
      assetXmlResponse = GenerateRequestAndGetResponse("POST", "Assets", null, requestbody);

      Console.WriteLine("\nAsset Id: {0}", assetXmlResponse.GetElementsByTagName("Id")[0].InnerText);
      Console.WriteLine("Name: {0}", assetXmlResponse.GetElementsByTagName("Name")[0].InnerText);
      Console.WriteLine("State: {0}", assetXmlResponse.GetElementsByTagName("State")[0].InnerText);
      Console.WriteLine("Options: {0}", assetXmlResponse.GetElementsByTagName("Options")[0].InnerText);

      return assetXmlResponse;
    }


    private static XmlDocument CreateIngestManifest(string name)
    {
      XmlDocument manifestXmlResponse = null;

      manifestXmlResponse = GenerateRequestAndGetResponse("POST", "IngestManifests", null, "{ \"Name\" : \"" + name + "\" }");

      Console.WriteLine("\nManifest Id: {0}", manifestXmlResponse.GetElementsByTagName("Id")[0].InnerText);
      Console.WriteLine("Name: {0}", manifestXmlResponse.GetElementsByTagName("Name")[0].InnerText);
      Console.WriteLine("State: {0}", manifestXmlResponse.GetElementsByTagName("State")[0].InnerText);

      return manifestXmlResponse;
    }


    private static XmlDocument CreateIngestManifestAsset(string manifestId, string assetId)
    {
      XmlDocument manifestAssetXmlResponse = null;

      string requestbody;

      requestbody = "{ \"ParentIngestManifestId\": \"" + manifestId + "\", " +
                      "\"Asset\" : { \"Id\": \"" + assetId + "\" } }";


      // Generate HTTP request and pass in JSON defining the Asset's Id and the Manifest Id.    
      manifestAssetXmlResponse = GenerateRequestAndGetResponse("POST", "IngestManifestAssets", null, requestbody);

      Console.WriteLine("\nIngestManifestAsset Id: {0}", manifestAssetXmlResponse.GetElementsByTagName("Id")[0].InnerText);
      Console.WriteLine("ParentIngestManifest Id: {0}", manifestAssetXmlResponse.GetElementsByTagName("ParentIngestManifestId")[0].InnerText);

      return manifestAssetXmlResponse;
    }


    private static XmlDocument CreateIngestManifestFile(string manifestId, string manifestAssetId, string fileName, string encryptionKeyId = null)
    {
      XmlDocument manifestAssetFileXmlResponse = null;

      string requestbody;

      if (encryptionKeyId == null)
      {
        requestbody = "{ \"Name\" : \"" + fileName + "\", " +
        "\"ParentIngestManifestId\" : \"" + manifestId + "\", " +
        "\"ParentIngestManifestAssetId\" : \"" + manifestAssetId + "\" " +
        "}";
      }
      else
      {
        requestbody = "{ \"Name\" : \"" + fileName + "\", " +
        "\"ParentIngestManifestId\" : \"" + manifestId + "\", " +
        "\"ParentIngestManifestAssetId\" : \"" + manifestAssetId + "\", " +
        "\"IsEncrypted\" : \"true\", " +
        "\"EncryptionScheme\" : \"StorageEncryption\", " +
        "\"EncryptionVersion\" : \"1.0\", " +
        "\"EncryptionKeyId\" : \"" + encryptionKeyId + "\" " +
        "}";
      }


      // Generate HTTP request and pass in JSON defining the Asset's name.    
      manifestAssetFileXmlResponse = GenerateRequestAndGetResponse("POST", "IngestManifestFiles", null, requestbody);

      Console.WriteLine("\nIngestManifestFile Id: {0}", manifestAssetFileXmlResponse.GetElementsByTagName("Id")[0].InnerText);

      return manifestAssetFileXmlResponse;
    }


    private static XmlDocument GetEntity(string resourcePath, string query = null)
    {
      XmlDocument xmlResponse = null;

      xmlResponse = GenerateRequestAndGetResponse("GET", resourcePath, query, null);

      return xmlResponse;
    }


    private static void PollIngestManifestStatisticsToCompletion(string manifestId)
    {
      int pollInterval = 30000; // ms

      Console.WriteLine("\nBulk Ingest Statistics Polling Interval : {0} sec.\n", pollInterval / 1000);

      bool bContinue = true;

      while (bContinue)
      {
        XmlDocument manifest = GetEntity("IngestManifests('" + manifestId + "')");

        Console.WriteLine("Waiting on all file uploads.");
        Console.WriteLine("PendingFilesCount: " + manifest.GetElementsByTagName("PendingFilesCount")[0].InnerText);
        Console.WriteLine("FinishedFilesCount: " + manifest.GetElementsByTagName("FinishedFilesCount")[0].InnerText);
        Console.WriteLine("ErrorFilesCount: " + manifest.GetElementsByTagName("ErrorFilesCount")[0].InnerText);
        Console.WriteLine("ErrorFilesDetails: {0}\n", manifest.GetElementsByTagName("ErrorFilesDetails")[0].InnerText);

        if (Convert.ToInt32(manifest.GetElementsByTagName("PendingFilesCount")[0].InnerText) == 0)
          bContinue = false;
        else
          System.Threading.Thread.Sleep(pollInterval);
      }
    }



    private static XmlDocument CreateContentKey(int encryptionType)
    {
      XmlDocument contentKeyXmlResponse = null;

      AesCryptoServiceProvider myAes = new AesCryptoServiceProvider();

      // This value of myAes.Key will be the 256 byte content key that must be used for encrypting the file before upload. //
      byte[] contentKey = myAes.Key;
      Console.WriteLine("\nUnencrypted content key : {0}\n", Convert.ToBase64String(contentKey));

      if (encryptionType != 1)
        return null;

      //===[ Get the protection key Id for StorageEncryption(1) X.509 certificate ]=================================//
      XmlDocument xmlProtectionKeyId = GetEntity("GetProtectionKeyId", "contentKeyType=" + encryptionType.ToString());
      string protectionKeyId = xmlProtectionKeyId.GetElementsByTagName("GetProtectionKeyId")[0].InnerText;

      //===[ Get the protection key for StorageEncryption(1) X.509 certificate ]==============================//
      XmlDocument xmlProtectionKey = GetEntity("GetProtectionKey", "ProtectionKeyId='" + protectionKeyId + "'");

      //===[ use the X509Certificate2 class to create a RSACryptoServiceProvider to use for encryption ]===//
      string certString = xmlProtectionKey.GetElementsByTagName("GetProtectionKey")[0].InnerText;
      byte[] certBytes = Convert.FromBase64String(certString);
      X509Certificate2 certToUse = new X509Certificate2(certBytes);
      var rsaProvider = (RSACryptoServiceProvider)certToUse.PublicKey.Key;

      //===[ Encrypt the content key using the RSACryptoServiceProvider ]=============================//
      string encryptedContentKey = Convert.ToBase64String(rsaProvider.Encrypt(contentKey, false));
      Console.WriteLine("Encrypted content key : {0}\n", encryptedContentKey);

      //===[ NOTE: ContentKey has user-defined Id value ]===//
      var contentKeyGuidId = Guid.NewGuid();

      //===[ Generate a MD5 checksum of the 
      string checkSumMD5 = CalculateContentKeyChecksum(contentKey, contentKeyGuidId);

      string requestBody = "{\"Id\" : \"nb:kid:UUID:" + contentKeyGuidId + "\", " +
                            "\"ContentKeyType\" : 1, " +
                            "\"EncryptedContentKey\" : \"" + encryptedContentKey + "\", " +
                            "\"ProtectionKeyId\" : \"" + protectionKeyId + "\", " +
                            "\"ProtectionKeyType\" : " + encryptionType.ToString() + ", " +
                            "\"Checksum\" : \"" + checkSumMD5 + "\" }";

      contentKeyXmlResponse = GenerateRequestAndGetResponse("POST", "ContentKeys", null, requestBody);

      string contentKeyId = contentKeyXmlResponse.GetElementsByTagName("Id")[0].InnerText;
      Console.WriteLine("ContentKey Id: {0}\n", contentKeyId);

      // From __metadata uri element...
      string contentKeyUri = contentKeyXmlResponse.GetElementsByTagName("uri")[0].InnerText;
      Console.WriteLine("__metadata uri : {0}", contentKeyUri);

      return contentKeyXmlResponse;
    }


    public static string CalculateContentKeyChecksum(byte[] contentKey, Guid keyId)
    {
      const int ChecksumLength = 8;
      const int KeyIdLength = 16;

      byte[] encryptedKeyId = null;

      // Checksum is computed by AES-ECB encrypting the KID
      // with the content key.
      using (AesCryptoServiceProvider rijndael = new AesCryptoServiceProvider())
      {
        rijndael.Mode = CipherMode.ECB;
        rijndael.Key = contentKey;
        rijndael.Padding = PaddingMode.None;

        ICryptoTransform encryptor = rijndael.CreateEncryptor();
        encryptedKeyId = new byte[KeyIdLength];
        encryptor.TransformBlock(keyId.ToByteArray(), 0, KeyIdLength, encryptedKeyId, 0);
      }

      byte[] retVal = new byte[ChecksumLength];
      Array.Copy(encryptedKeyId, retVal, ChecksumLength);

      return Convert.ToBase64String(retVal);
    }


    private static void LinkContentKeyToAsset(string assetId, string contentKeyUri)
    {
      XmlDocument xmlResponse = GenerateRequestAndGetResponse("POST", "Assets('" + assetId + "')/$links/ContentKeys", null, "{ \"uri\": \"" + contentKeyUri + "\"}");
    }
  }
}

Consulte também

Mostrar:
© 2014 Microsoft