C# 如何跟踪异步文件上载到azure存储的进度
是否有方法跟踪文件上载到Azure存储容器的进度?我正在尝试制作一个控制台应用程序,用于使用C#将数据上传到Azure 我当前的代码如下所示:C# 如何跟踪异步文件上载到azure存储的进度,c#,file-upload,azure,azure-storage,azure-storage-blobs,C#,File Upload,Azure,Azure Storage,Azure Storage Blobs,是否有方法跟踪文件上载到Azure存储容器的进度?我正在尝试制作一个控制台应用程序,用于使用C#将数据上传到Azure 我当前的代码如下所示: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Auth; using Micro
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System.Configuration;
using System.IO;
using System.Threading;
namespace AdoAzure
{
class Program
{
static void Main(string[] args)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("adokontajnerneki");
container.CreateIfNotExists();
CloudBlobClient myBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlockBlob myBlob = container.GetBlockBlobReference("racuni.adt");
CancellationToken ca = new CancellationToken();
var ado = myBlob.UploadFromFileAsync(@"c:\bo\racuni.adt", FileMode.Open, ca);
Console.WriteLine(ado.Status); //Does Not Help Much
ado.ContinueWith(t =>
{
Console.WriteLine("It is over"); //this is working OK
});
Console.WriteLine(ado.Status); //Does Not Help Much
Console.WriteLine("theEnd");
Console.ReadKey();
}
}
}
这段代码运行得很好,但我希望有某种进度条,这样用户就可以看到正在运行的任务。WindowsAzure.Storage.Blob名称空间中是否有我可以使用的东西,比如帽子里的兔子?我认为这是不可能的,因为上传文件是一项单独的任务,即使在内部文件被分成多个块,这些块被上传,代码实际上也会等待整个任务完成 一种可能是手动将文件分割成块,并使用方法异步上传这些块。一旦上传了所有块,就可以调用方法来提交blob。请参阅下面的代码,它实现了以下功能:
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials("accountname", "accountkey"), true);
static void Main(string[] args)
{
CloudBlobClient myBlobClient = storageAccount.CreateCloudBlobClient();
myBlobClient.SingleBlobUploadThresholdInBytes = 1024 * 1024;
CloudBlobContainer container = myBlobClient.GetContainerReference("adokontajnerneki");
//container.CreateIfNotExists();
CloudBlockBlob myBlob = container.GetBlockBlobReference("cfx.zip");
var blockSize = 256 * 1024;
myBlob.StreamWriteSizeInBytes = blockSize;
var fileName = @"D:\cfx.zip";
long bytesToUpload = (new FileInfo(fileName)).Length;
long fileSize = bytesToUpload;
if (bytesToUpload < blockSize)
{
CancellationToken ca = new CancellationToken();
var ado = myBlob.UploadFromFileAsync(fileName, FileMode.Open, ca);
Console.WriteLine(ado.Status); //Does Not Help Much
ado.ContinueWith(t =>
{
Console.WriteLine("Status = " + t.Status);
Console.WriteLine("It is over"); //this is working OK
});
}
else
{
List<string> blockIds = new List<string>();
int index = 1;
long startPosition = 0;
long bytesUploaded = 0;
do
{
var bytesToRead = Math.Min(blockSize, bytesToUpload);
var blobContents = new byte[bytesToRead];
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
fs.Position = startPosition;
fs.Read(blobContents, 0, (int)bytesToRead);
}
ManualResetEvent mre = new ManualResetEvent(false);
var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6")));
Console.WriteLine("Now uploading block # " + index.ToString("d6"));
blockIds.Add(blockId);
var ado = myBlob.PutBlockAsync(blockId, new MemoryStream(blobContents), null);
ado.ContinueWith(t =>
{
bytesUploaded += bytesToRead;
bytesToUpload -= bytesToRead;
startPosition += bytesToRead;
index++;
double percentComplete = (double)bytesUploaded / (double)fileSize;
Console.WriteLine("Percent complete = " + percentComplete.ToString("P"));
mre.Set();
});
mre.WaitOne();
}
while (bytesToUpload > 0);
Console.WriteLine("Now committing block list");
var pbl = myBlob.PutBlockListAsync(blockIds);
pbl.ContinueWith(t =>
{
Console.WriteLine("Blob uploaded completely.");
});
}
Console.ReadKey();
}
}
}
使用Microsoft.WindowsAzure.Storage;
使用Microsoft.WindowsAzure.Storage.Auth;
使用Microsoft.WindowsAzure.Storage.Blob;
使用制度;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
班级计划
{
静态CloudStorageAccount storageAccount=新的CloudStorageAccount(新的StorageCredentials(“accountname”、“accountkey”),true);
静态void Main(字符串[]参数)
{
CloudBlobClient myBlobClient=storageAccount.CreateCloudBlobClient();
myBlobClient.SingleBlobUploadThresholdInBytes=1024*1024;
CloudBlobContainer container=myBlobClient.GetContainerReference(“adokontajnerneki”);
//container.CreateIfNotExists();
CloudBlockBlob myBlob=container.GetBlockBlobReference(“cfx.zip”);
var blockSize=256*1024;
myBlob.StreamWriteSizeInBytes=块大小;
var fileName=@“D:\cfx.zip”;
long bytesToUpload=(新文件信息(文件名)).Length;
long fileSize=bytesToUpload;
if(bytesToUpload
{
Console.WriteLine(“Status=“+t.Status”);
Console.WriteLine(“结束”);//这工作正常
});
}
其他的
{
List blockIds=新列表();
int指数=1;
长起始位置=0;
长字节数=0;
做
{
var bytesToRead=Math.Min(块大小,bytesToUpload);
var blobContents=新字节[bytesToRead];
使用(FileStream fs=newfilestream(fileName,FileMode.Open))
{
fs.位置=起始位置;
读取(blobContents,0,(int)bytesToRead);
}
ManualResetEvent mre=新的ManualResetEvent(错误);
var blockId=Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString(“d6”));
Console.WriteLine(“现在正在上传块#”+index.ToString(“d6”);
blockId.Add(blockId);
var ado=myBlob.putblocksync(blockId,新内存流(blobContents),null);
ado.ContinueWith(t=>
{
bytesUpload+=bytesToRead;
bytesToUpload-=bytesToRead;
startPosition+=bytesToRead;
索引++;
完成双百分比=(双)字节上载/(双)文件大小;
Console.WriteLine(“完成百分比=”+完成百分比.ToString(“P”);
mre.Set();
});
韦通先生();
}
while(bytesToUpload>0);
WriteLine(“正在提交阻止列表”);
var pbl=myBlob.PutBlockListAsync(blockIds);
pbl.ContinueWith(t=>
{
Console.WriteLine(“Blob已完全上传”);
});
}
Console.ReadKey();
}
}
}
Gaurav的解决方案运行良好,与之非常相似。这段代码的挑战在于,您只需很少的错误处理就可以完成大量复杂的工作。我并不是说Gaurav的代码有什么问题——它看起来很可靠——但特别是与网络相关的通信代码,有很多变量和问题需要解释
出于这个原因,我修改了我的原始博客,使用存储客户端库中的上载代码(假设来自Azure存储团队的代码比我所能编写的任何代码都更健壮),并使用ProgressStream类跟踪进度。您可以在上看到更新的代码。这个怎么样
public类observeFileStream:FileStream
{
私人行动;
public observeFileStream(字符串文件名,文件模式,动作回调):base(文件名,模式)
{
_回调=回调;
}
公共重写无效写入(字节[]数组、整数偏移量、整数计数)
{
_回调?.Invoke(长度);
写入(数组、偏移量、计数);
}
公共重写整型读取(字节[]数组、整型偏移量、整型计数)
{
_回调?.Invoke(位置);
返回base.Read(数组、偏移量、计数);
}
}
公共类测试
{
私有异步无效上载(字符串文件路径、CloudBlockBlob blob)
{
可观测流fs=nu
public void UploadBlob(string fileToUploadPath)
{
var file = new FileInfo(fileToUploadPath);
uploadFileSize = file.Length; //Get the file size. This is need to calculate the file upload progress
//Initialize a progress handler. When the file is being uploaded, the current uploaded bytes will be published back to us using this progress handler by the Blob Storage Service
var progressHandler = new Progress();
progressHandler.ProgressChanged += UploadProgressChanged;
var blob = new BlobClient(connectionString, containerName, file.Name); //Initialize the blob client
blob.Upload(fileToUploadPath, progressHandler: progressHandler); //Make sure to pass the progress handler here
}
private void UploadProgressChanged(object sender, long bytesUploaded)
{
//Calculate the progress and update the progress bar.
//Note: the bytes uploaded published back to us is in long. In order to calculate the percentage, the value has to be converted to double.
//Auto type casting from long to double happens here as part of function call
Console.WriteLine(GetProgressPercentage(uploadFileSize, bytesUploaded));
}
private double GetProgressPercentage(double totalSize,double currentSize)
{
return (currentSize / totalSize) * 100;
}
private const string StorageConnectionString = "<Your storage connection string>";
private const string StorageContainerName = "<Your storage container name>";
[HttpPost]
public async Task<IActionResult> UploadFiles(IList<IFormFile> files)
{
foreach (var file in files)
{
var blockBlobClient = new BlockBlobClient(StorageConnectionString, StorageContainerName, file.FileName); // Add Guid to FileName to ensure uniqueness
using var output = blockBlobClient.OpenWrite(overwrite: true);
using var input = file.OpenReadStream();
var buffer = new byte[64 * 1024];
var totalReadBytes = 0L;
var readBytes = 0;
while ((readBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
await output.WriteAsync(buffer, 0, readBytes);
totalReadBytes += readBytes;
//progress = Math.Round((totalReadBytes * 1d / sessionUploadFileInfo.FileLength * 100d), 2, MidpointRounding.AwayFromZero);
//do what you do with the progress, save it in session or however you display it to the user...
//With WebAPI, I use a static dictionary and a client Id to store file upload progress
//A separate REST request with client Id gets the file progress' from the dictionary
}
}
return Content("success");
}