Загрузка в службы мультимедиа Azure / хранилище больших двоичных объектов с SasLocator не показывает загруженный файл - PullRequest
0 голосов
/ 31 мая 2018

Итак, я хочу выгрузить видео из клиентского настольного приложения в Azure Media Services (которая, конечно, использует хранилище Azure).

Я пытаюсь создать комбинацию из:

Первый показывает прекрасный пример моего сценария, но второй иллюстрирует, как использовать BlobTransferClient для загрузки нескольких файлов и иметь индикатор «прогресс».

проблема: кажется, что загрузка происходит, и я не получаю никакой ошибки после загрузки, но на портале Azure / в учетной записи хранилища ничего не отображается.Кажется, что загрузка происходит потому, что задача занимает много времени, диспетчер задач показывает прогресс загрузки Wi-Fi, а хранилище Azure показывает, что (успешные) запросы выполняются.

Итак, на сервере я временно создаю SasLocator:

public async Task<VideoUploadModel> GetSasLocator(string filename)
{

    var assetName = filename + DateTime.UtcNow;

    IAsset asset = await _context.Assets.CreateAsync(assetName, AssetCreationOptions.None, CancellationToken.None);

    IAccessPolicy accessPolicy = _context.AccessPolicies.Create(assetName, TimeSpan.FromMinutes(10),
        AccessPermissions.Write);

    var locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);

    var blobUri = new UriBuilder(locator.Path);
    blobUri.Path += "/" + filename;

    var model = new VideoUploadModel()
    {
        Filename = filename,
        AssetName = assetName,
        SasLocator = blobUri.Uri.AbsoluteUri,
        AssetId = asset.Id
    };
    return model;
}

И на стороне клиента я пытаюсь загрузить:

public async Task UploadVideoFileToBlobStorage(string[] files, string sasLocator, CancellationToken cancellationToken)
{
    var blobUri = new Uri(sasLocator);
    var sasCredentials = new StorageCredentials(blobUri.Query);

    //var blob = new CloudBlockBlob(new Uri(blobUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)), sasCredentials);
    var blobClient = new CloudBlobClient(new Uri(blobUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)), sasCredentials);
    var blobTransferClient = new BlobTransferClient(TimeSpan.FromMinutes(1))
    {
        NumberOfConcurrentTransfers = 2,
        ParallelTransferThreadCount = 2
    };
    //register events
    blobTransferClient.TransferProgressChanged += BlobTransferClient_TransferProgressChanged;
    //files
    var uploadTasks = new List<Task>();
    foreach (var filePath in files)
    {
        await blobTransferClient.UploadBlob(blobUri, filePath, new FileEncryption(), cancellationToken, blobClient, new NoRetry());
    }



    //StorageFile storageFile = null;

    //if (string.IsNullOrEmpty(file.FutureAccessToken))
    //{
    //    storageFile = await StorageFile.GetFileFromPathAsync(file.Path).AsTask(cancellationToken);
    //}
    //else
    //{
    //    storageFile = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(file.FutureAccessToken).AsTask(cancellationToken);
    //}
    //cancellationToken.ThrowIfCancellationRequested();
    //await blob.UploadFromFileAsync(storageFile);
}

Я знаю, что, вероятно, я неправильно делаю это с именами активов и использую индикатор прогресса вместо await, но, конечно,Сначала я хочу, чтобы это работало, прежде чем закончить.

Я настроил службы мультимедиа Azure на «Подключение к службам мультимедиа API с субъектом службы», где я создал новое приложение Azure AD и сгенерировал для этого ключи, например эта страница документации .Я не совсем уверен, как это работает, немного неопытный в приложениях Azure AD и Azure AD (руководство?).

Загрузка:

uploading of asset

Актив создан, но файлов нет:

media services

В хранилище также не отображаются файлы:

blob containers

Хранилище показывает успешную загрузку:

statistics

Причина, по которой я не могу точно выполнить загрузку Несколько файлов с документацией Media Services .NET SDK , потому что он использует _context (то есть Microsoft.WindowsAzure.MediaServices.Client.CloudMediaContext), что _context я могу использовать на стороне сервера, но не на стороне клиента, потому что для этого требуется конечная точка TentantDomain, RESTAPI,ClientId и Client Secret.

Я думаю, что загрузка через SaSLocator является правильным способом (?).

ОБНОВЛЕНИЕ 1

При загрузке с помощью CloudBlockBlobон снова загружается и отображается в моей учетной записи хранения в активе, но когда я захожу в медиа-службы в рамках Azure и нажимаю на нужнуюактив, он не показывает никаких файлов.

Итак, код для этого:

var blob = new CloudBlockBlob(new Uri(blobUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)), sasCredentials);
//files
var uploadTasks = new List<Task>();
foreach (var filePath in files)
{
    await blob.UploadFromFileAsync(filePath, CancellationToken.None);
}

Я также пытался загрузить ресурс вручную в Azure.Итак, нажмите «Загрузить» в меню «Актив», затем «Кодировать».Все это прекрасно работает.

ОБНОВЛЕНИЕ 2:

Копание глубже Я нашел следующий, еще не проверенный на практике, способ заставить его работать в данный момент:

1. Получить подпись общего доступа непосредственно из хранилища и загрузить ее туда:

public static async Task<string> GetMediaSasLocator(string filename)
{
    CloudBlobContainer cont = await GetMediaContainerAsync();
    SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy()
    {
        SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddMinutes(60),
        Permissions = SharedAccessBlobPermissions.Write,
        SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5)
    };
    await cont.FetchAttributesAsync();

    return cont.Uri.AbsoluteUri + "/" + filename + cont.GetSharedAccessSignature(policy);
}

С помощью этого SaS я могу загрузить, как я показал в ОБНОВЛЕНИИ 1, ничегоизменилось там.

2. Создайте функцию Azure (которая уже была запланирована), которая обрабатывает создание актива, загрузку файла в актив, кодирование и публикацию.Это было сделано с помощью этого учебника: Инструменты функций Azure для Visual Studio , а затем реализован код, показанный в Загрузка нескольких файлов с помощью Media Services .NET SDK .

Так что это "работает", но еще не идеально, у меня все еще нет индикатора прогресса в моем клиентском WPF-приложении, а функция Azure выполняется довольно долго, потому что мы в основном "загружаем" файлснова в актив после того, как он уже находится в хранилище Azure.Я скорее использую метод для копирования из одного контейнера в контейнер активов.

Я пришел к этому моменту, потому что функциям Azure нужно фиксированное заданное имя контейнера, поскольку ресурсы создают свои собственные контейнеры в учетной записи хранения, для них нельзя вызвать функцию Azure.Поэтому для работы с функциями Azure мне кажется, что мне действительно нужно загрузить его на фиксированное имя контейнера, а затем сделать все остальное.

По-прежнему остается вопрос: Зачем загружать видеофайл в хранилище Azure черезBlobTransferClient не работает?И если это сработает, как мне вызвать функцию Azure на основе нескольких контейнеров.«Путь», как asset- {name} / {name} .avi, будет предпочтительным.

1 Ответ

0 голосов
/ 05 июня 2018

В конце концов оказалось, что мне нужно указать базовый URL в методе UploadBlob, поэтому без самого имени файла, которое находится в URL-адресе SasLocator, но только с именем контейнера.

Как только я исправил это, я также заметил, что он не загружается в имя файла, которое я указал в серверной части SasLocator, которую я создал (он включает префикс customerID).Мне пришлось использовать одну из других перегрузок метода, чтобы получить правильное имя файла.

public async Task UploadVideoFilesToBlobStorage(List<VideoUploadModel> videos, CancellationToken cancellationToken)
{
    var blobTransferClient = new BlobTransferClient();
    //register events
    blobTransferClient.TransferProgressChanged += BlobTransferClient_TransferProgressChanged;
    //files
    _videoCount = _videoCountLeft = videos.Count;
    foreach (var video in videos)
    {
        var blobUri = new Uri(video.SasLocator);
        //create the sasCredentials
        var sasCredentials = new StorageCredentials(blobUri.Query);
        //get the URL without sasCredentials, so only path and filename.
        var blobUriBaseFile = new Uri(blobUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path,
            UriFormat.UriEscaped));
        //get the URL without filename (needed for BlobTransferClient (seems to me like a issue)
        var blobUriBase = new Uri(blobUriBaseFile.AbsoluteUri.Replace("/"+video.Filename, ""));

        var blobClient = new CloudBlobClient(blobUriBaseFile, sasCredentials);
        //upload using stream, other overload of UploadBlob forces to put online filename of local filename
        using (FileStream fs = new FileStream(video.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            await blobTransferClient.UploadBlob(blobUriBase, video.Filename, fs, null, cancellationToken, blobClient, 
                new NoRetry(), "video/x-msvideo");
        }
        _videoCountLeft -= 1;
    }

    blobTransferClient.TransferProgressChanged -= BlobTransferClient_TransferProgressChanged;
}

private void BlobTransferClient_TransferProgressChanged(object sender, BlobTransferProgressChangedEventArgs e)
{
    Console.WriteLine("progress, seconds remaining:" + e.TimeRemaining.Seconds);
    double bytesTransfered = e.BytesTransferred;
    double bytesTotal = e.TotalBytesToTransfer;
    double thisProcent = bytesTransfered / bytesTotal;
    double procent = thisProcent;
    //devide by video amount
    int videosUploaded = _videoCount - _videoCountLeft;
    if (_videoCountLeft > 0)
    {
        procent = (thisProcent + videosUploaded) / _videoCount;
    }

    procent = procent * 100;//to real %
    UploadProgressChangedEvent?.Invoke((int)procent, videosUploaded, _videoCount);
}

На самом деле Microsoft.WindowsAzure.MediaServices.Client.BlobTransferClient должен иметь возможность выполнять одновременную загрузку, но нет метода для загрузки нескольких файлов, но у него есть свойства для NumberOfConcurrentTransfers и ParallelTransferThreadCount, не знаю, как это использовать.

Я не проверял, работает ли теперь это и с Активами, потому что теперь я загружаю в 1 отдельный контейнер для каждого файла, а затем использую Azure.Функция для обработки актива, главным образом потому, что я не могу вызвать функцию Azure для динамического имени контейнера (каждый актив создает свой собственный контейнер).

...