C# 大文件下载可从 azure blob 存储恢复
C# big filedownload resumable from azure blob storage
我真的需要一些橡皮鸭...
我有一个至少为 2.3 GiB 的文件。
我目前正在将此文件下载到临时目录。
但是当下载中断时(连接错误,或 windows 崩溃)我希望用户从停止的地方恢复下载。而不是重新下载整个文件。
该代码的工作原理是它继续下载文件,但我看到下载流又从头开始了。所以这意味着文件最终为(2.3 GiB + 之前下载的字节数),这会损坏我的文件。
我使用了以下代码片段来恢复下载,所以我希望流能在停止的地方恢复
localStream.Seek(positionInFile, SeekOrigin.Begin);
关于我在这里遗漏的任何想法?
这是我的代码。
BlobContainerClient containerClient = new BlobContainerClient(connectionString, container);
var blobClient = containerClient.GetBlobClient(downloadFile);
fullOutputPath = createOutputFilePath(updateFileUri.OriginalString, outputFolder);
downloadFileInfo = new FileInfo(fullOutputPath);
var response = blobClient.Download(cts.Token);
contentLength = response.Value.ContentLength;
if (contentLength.HasValue && contentLength.Value > 0)
{
if (_fileSystemService.FileExists(fullOutputPath))
{
from = downloadFileInfo.Length;
to = contentLength;
if (from == to)
{
//file is already downloaded
//skip it
progress.Report(1);
return;
}
fileMode = FileMode.Open;
positionInFile = downloadFileInfo.Length;
}
using FileStream localStream = _fileSystemService.CreateFile(fullOutputPath, fileMode, FileAccess.Write);
localStream.Seek(positionInFile, SeekOrigin.Begin);
bytesDownloaded = positionInFile;
double dprog = ((double)bytesDownloaded / (double)(contentLength.Value + positionInFile));
do
{
bytesRead = await response.Value.Content.ReadAsync(buffer, 0, buffer.Length, cts.Token);
await localStream.WriteAsync(buffer, 0, bytesRead, cts.Token);
await localStream.FlushAsync();
bytesDownloaded += bytesRead;
dprog = ((double)bytesDownloaded / (double)(contentLength.Value + positionInFile));
progress.Report(dprog);
} while (bytesRead > 0);
}
我为您做了一些测试,就我而言,我使用.txt 文件来演示您的要求。您可以看到 .txt 文件 here。
如您所见,在第 151 行,我做了一个结束标记:
我还创建了一个以这个结束标记结尾的本地文件来模拟下载中断,我们将继续从存储中下载:
下面是我的快速演示代码:
static void Main(string[] args)
{
string containerName = "container name";
string blobName = ".txt file name";
string storageConnStr = "storage account conn str";
string localFilePath = @"local file path";
var localFileStream = new FileStream(localFilePath, FileMode.Append);
var localFileLength = new FileInfo(localFilePath).Length;
localFileStream.Seek(localFileLength, SeekOrigin.Begin);
var blobServiceClient = new BlobServiceClient(storageConnStr);
var blobClient = blobServiceClient.GetBlobContainerClient(containerName).GetBlobClient(blobName);
var stream = blobClient.Download(new Azure.HttpRange(localFileLength)).Value.Content;
var contentStrting = new StreamReader(stream).ReadToEnd();
Console.WriteLine(contentStrting);
localFileStream.Write(Encoding.ASCII.GetBytes(contentStrting));
localFileStream.Flush();
}
结果:
我们只下载了结束标志后面的内容:
内容已下载到本地 .txt 文件:
如果您还有其他问题,请告诉我。
我真的需要一些橡皮鸭...
我有一个至少为 2.3 GiB 的文件。 我目前正在将此文件下载到临时目录。 但是当下载中断时(连接错误,或 windows 崩溃)我希望用户从停止的地方恢复下载。而不是重新下载整个文件。 该代码的工作原理是它继续下载文件,但我看到下载流又从头开始了。所以这意味着文件最终为(2.3 GiB + 之前下载的字节数),这会损坏我的文件。
我使用了以下代码片段来恢复下载,所以我希望流能在停止的地方恢复 localStream.Seek(positionInFile, SeekOrigin.Begin);
关于我在这里遗漏的任何想法? 这是我的代码。
BlobContainerClient containerClient = new BlobContainerClient(connectionString, container);
var blobClient = containerClient.GetBlobClient(downloadFile);
fullOutputPath = createOutputFilePath(updateFileUri.OriginalString, outputFolder);
downloadFileInfo = new FileInfo(fullOutputPath);
var response = blobClient.Download(cts.Token);
contentLength = response.Value.ContentLength;
if (contentLength.HasValue && contentLength.Value > 0)
{
if (_fileSystemService.FileExists(fullOutputPath))
{
from = downloadFileInfo.Length;
to = contentLength;
if (from == to)
{
//file is already downloaded
//skip it
progress.Report(1);
return;
}
fileMode = FileMode.Open;
positionInFile = downloadFileInfo.Length;
}
using FileStream localStream = _fileSystemService.CreateFile(fullOutputPath, fileMode, FileAccess.Write);
localStream.Seek(positionInFile, SeekOrigin.Begin);
bytesDownloaded = positionInFile;
double dprog = ((double)bytesDownloaded / (double)(contentLength.Value + positionInFile));
do
{
bytesRead = await response.Value.Content.ReadAsync(buffer, 0, buffer.Length, cts.Token);
await localStream.WriteAsync(buffer, 0, bytesRead, cts.Token);
await localStream.FlushAsync();
bytesDownloaded += bytesRead;
dprog = ((double)bytesDownloaded / (double)(contentLength.Value + positionInFile));
progress.Report(dprog);
} while (bytesRead > 0);
}
我为您做了一些测试,就我而言,我使用.txt 文件来演示您的要求。您可以看到 .txt 文件 here。
如您所见,在第 151 行,我做了一个结束标记:
我还创建了一个以这个结束标记结尾的本地文件来模拟下载中断,我们将继续从存储中下载:
下面是我的快速演示代码:
static void Main(string[] args)
{
string containerName = "container name";
string blobName = ".txt file name";
string storageConnStr = "storage account conn str";
string localFilePath = @"local file path";
var localFileStream = new FileStream(localFilePath, FileMode.Append);
var localFileLength = new FileInfo(localFilePath).Length;
localFileStream.Seek(localFileLength, SeekOrigin.Begin);
var blobServiceClient = new BlobServiceClient(storageConnStr);
var blobClient = blobServiceClient.GetBlobContainerClient(containerName).GetBlobClient(blobName);
var stream = blobClient.Download(new Azure.HttpRange(localFileLength)).Value.Content;
var contentStrting = new StreamReader(stream).ReadToEnd();
Console.WriteLine(contentStrting);
localFileStream.Write(Encoding.ASCII.GetBytes(contentStrting));
localFileStream.Flush();
}
结果:
我们只下载了结束标志后面的内容:
内容已下载到本地 .txt 文件:
如果您还有其他问题,请告诉我。