簡體   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