【问题标题】:Get actual upload progress on Azure Blob获取 Azure Blob 上的实际上传进度
【发布时间】:2014-02-09 22:08:56
【问题描述】:

我知道这已经被问过了,但标记的解决方案不正确。通常这篇文章被标记为解决方案:https://docs.microsoft.com/en-us/archive/blogs/kwill/asynchronous-parallel-blob-transfers-with-progress-change-notification-2-0

它有效并给出了实际进度,但不是实时进度(在某些情况下,它给出了一个完全错误的值)。让我解释一下:

它给出了本地读取缓冲区的进度,所以当我上传东西时,我的第一个“上传值”是读取缓冲区的总大小。在我的情况下,这个缓冲区是 4mb,因此每个小于 4mb 的文件都会在 0 秒内完成进度条,但它需要真正的上传时间才能真正完成。

另外,如果您尝试在上传开始之前终止连接,它会给出第一个缓冲区大小作为实际进度,所以对于我的 1mb 文件,我在 断开连接时获得 100% 的进度。

我发现另一个解决方案的另一篇文章,它每次完成单个块上传时都会从 azure 读取 http 响应,但我需要我的块为 4mb(因为单个文件的最大块数是 50.000),即使块大小很小,它也不是一个完美的解决方案。

第一篇文章覆盖流类并创建一个ProgressStream 类,每次读取完成时都会触发ProgressChanged 事件,有一些方法可以知道实际上传的字节什么时候触发ProgressChanged

【问题讨论】:

  • 您能否解释一下您的意思:but i need my blocks to be 4mb (since max block count for a single file is 50.000) and its not a perfect solution even with low block size
  • @GauravMantri 我的意思是,因为我可以知道块上传何时完成,如果我上传 250kb 的块 blob(仅作为示例),我可以知道 250kb 错误的上传进度(仍然不可接受)。另外,单个块 blob 最多可以有 50.000 个块,因此我的最大单个文件大小变为 250kb * 50.000 = 12.5gb(不是最佳的)。块越小精度越高,但最大文件越小:(

标签: c# file-upload azure upload progress


【解决方案1】:

您可以通过使用类似于 https://docs.microsoft.com/en-us/archive/blogs/kwill/asynchronous-parallel-block-blob-transfers-with-progress-change-notification(您引用的博客文章的 1.0 版)的代码来执行此操作,但您无需调用 m_Blob.PutBlock 而是使用 HTTPWebRequest 对象上传块并使用来自HTTPWebRequest 类。这会带来更多的代码复杂性,并且您必须添加一些额外的错误处理。

另一种方法是从GitHub 下载存储客户端库源代码并修改块上传方法以跟踪和报告进度。您将面临的挑战是,如果您打算及时了解最新的修复程序,则必须对每个新版本的 SCL 进行同样的更改。

【讨论】:

  • 对不起,如果我在标记为解决方案之前等待,我需要一些时间来成功实施它!我使用了您的第一个解决方案并且效果很好,现在我可以看到我的进度条具有正确的值,并且感觉我可以 100% 控制上传发生的事情 :) 当然,嵌入的 azure sdk 方法确实更容易实现,但现在我得到了我想要的结果:) 谢谢!
【解决方案2】:

我必须承认,我没有检查一切是否如您所愿,但这是我的 2 美分上传进度指示。

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的属性,不知道怎么用。

这个BlobTransferClient 有一个错误,当使用localFile 参数上传时,它将使用该文件的文件名,而我在 SaSLocator 中授予了特定文件名的权限。

这个例子展示了如何从客户端(而不是服务器)上传,所以我们不需要任何CloudMediaContext,通常情况下。关于 SasLocators 的一切都可以在here 找到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-07
    • 2019-12-22
    • 2021-03-02
    • 1970-01-01
    • 2016-11-14
    • 2021-03-27
    • 2012-04-15
    • 2021-03-24
    相关资源
    最近更新 更多