我知道已经提出过这个问题,但标记的解决方案并不正确。通常,本文标记为解决方案:http://blogs.msdn.com/b/kwill/archive/2013/03/06/asynchronous-parallel-block-blob-transfers-with-progress-change-notification-2-0.aspx
它可以工作并提供实际进度,但不是实时进度(在某些情况下,它会提供完全错误的值)。让我解释一下:
它提供了本地读取缓冲区的进度,因此当我上传内容时,我的第一个“上传的值”是读取缓冲区的总大小。在我的情况下,这个缓冲区是4mb,所以每个小于4mb的文件结果在0秒内完成进度条,但它需要真正的上传时间才能完成。
此外,如果您尝试在上传开始之前终止连接,则会将第一个缓冲区大小作为实际进度,因此对于我的1mb文件,我在断开连接时获得100%的进展。
我发现另一篇文章有另一个解决方案,它每次完成单个块上传时都会从azure读取http响应,但我需要我的块 4mb (因为单个文件的最大块数)是50.000)并且即使块尺寸较小也不是完美的解决方案。
第一篇文章覆盖了流类并创建了一个ProgressStream
类,其中每次读取完成时都会触发ProgressChanged
事件,有一些方法可以知道实际在触发ProgressChanged
时上传的字节数?
答案 0 :(得分:2)
您可以使用类似于http://blogs.msdn.com/b/kwill/archive/2011/05/30/asynchronous-parallel-block-blob-transfers-with-progress-change-notification.aspx的代码(您引用的博客文章的1.0版)来执行此操作,但不是调用m_Blob.PutBlock而是使用HTTPWebRequest对象上传块并使用progress事件来自HTTPWebRequest类。这会引入更多代码复杂性,您必须添加一些额外的错误处理。
另一种方法是从GitHub下载Storage Client Library源代码,并修改块上传方法以跟踪和报告进度。您将面临的挑战是,如果您计划及时了解最新的修补程序,则必须对每个新版本的SCL进行相同的更改。
答案 1 :(得分:0)
我必须承认我没有检查是否所有内容都符合您的要求,但这是我上传时带有进度指示的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
应该可以进行并发上传,但没有上传多个方法,但它有NumberOfConcurrentTransfers
和ParallelTransferThreadCount
的属性,不知道如何使用它。
此BlobTransferClient
中存在一个错误,当使用localFile
参数上传时,它将使用该文件的文件名,而我在SaSLocator中授予特定文件名的权限。
此示例显示如何从客户端(而不是在服务器上)上传,因此我们通常不需要任何CloudMediaContext
。关于SasLocators的一切都可以找到here。