繁体   English   中英

使用 SasLocator 不显示上传的文件上传到 Azure 媒体服务/blob 存储

[英]Upload to Azure Media Services / blob storage with SasLocator not showing uploaded file

所以我想将视频从客户端桌面应用程序上传到 Azure 媒体服务(当然使用 Azure 存储)。

我正在尝试进行以下组合:

第一个展示了我的场景的完美示例,但第二个说明了如何使用BlobTransferClient上传多个文件并具有“进度”指示器。

问题:它似乎确实上传了,上传后我没有收到任何错误,但 Azure 门户/存储帐户中没有显示任何内容。 上传似乎是因为任务需要很长时间,任务管理器显示 wifi 上传进度,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);
}

我知道我可能没有正确地命名资产并使用进度指示器而不是等待,但当然我首先希望它在完成之前先工作。

我将 Azure 媒体服务配置为“使用服务主体连接到媒体服务 API”,我在其中创建了一个新的 Azure AD 应用程序并为此生成了密钥,例如文档页面 我不太确定这究竟是如何工作的,对 Azure AD 和 Azure AD 应用程序几乎没有经验(指导?)。

上传:

上传资产

资产已创建但没有文件:

媒体服务

存储也不显示任何文件:

Blob 容器

存储确实显示成功上传:

统计数据

我不能完全遵循使用媒体服务 .NET SDK文档上传多个文件的原因是因为它使用_context (即Microsoft.WindowsAzure.MediaServices.Client.CloudMediaContext ),即_context我可以使用服务器端但不能使用客户端因为它需要 TentantDomain、RESTAPI Endpoint、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,我可以像我在 UPDATE 1 中展示的那样上传,那里没有任何改变。

2.创建一个 Azure 函数(已经计划这样做),它处理资产创建、文件上传到资产、编码和发布。 这是通过遵循本教程完成的: 用于 Visual Studio 的 Azure 函数工具,然后实现使用媒体服务 .NET SDK 上传多个文件中说明的代码。

所以这个“有效”但还不完美,我的客户端 WPF 应用程序中仍然没有我的进度指示器,Azure 函数需要很长时间才能完成,因为我们基本上在它之后再次“上传”文件到资产已在 Azure 存储中。 我宁愿使用一种方法从一个容器复制到资产容器。

我走到这一步是因为 Azure 函数需要一个固定的给定容器名称,因为资产在存储帐户中创建自己的容器,因此您无法在这些容器上触发 Azure 函数。 因此,要使用 Azure Functions,似乎我真的必须将它上传到一个固定的容器名称,然后再做其余的工作。

问题仍然存在:为什么通过BlobTransferClient将视频文件上传到 Azure 存储不起作用? 如果可行,我如何触发基于多个容器的 Azure 功能。 像 asset-{name}/{name}.avi 这样的“路径”将是首选。

最终结果是我需要在UploadBlob方法中指定基本 URL ,所以没有文件名本身,它在 SasLocator URL 中,而只有容器名称。

一旦我解决了这个问题,我还注意到它没有上传到我在 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应该能够进行并发上传,但没有上传多个的方法,但它具有NumberOfConcurrentTransfersParallelTransferThreadCount属性,不知道如何使用它。

我没有检查这现在是否也适用于资产,因为我现在为每个文件上传到 1 个单个容器,然后使用 Azure 函数处理资产,主要是因为我无法在动态上触发 Azure 函数容器名称(每个资产创建自己的容器)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM