#c# #azure #azure-storage
#c# #azure #azure-хранилище
Вопрос:
Мне действительно нужно немного резинового ныряния…
У меня есть файл размером не менее 2,3 гигабайт. В настоящее время я загружаю этот файл во временный каталог. Но когда загрузка прерывается (ошибка подключения или сбой Windows) Я хочу, чтобы пользователь возобновил загрузку с того места, где она остановилась. И не скачивать весь файл заново. Код работает в том смысле, что он продолжает загрузку файла, но я вижу, что поток загрузки снова начинается с самого начала. Таким образом, это означает, что файл заканчивается (2,3 гигабайта количество байт, которые были загружены ранее), что, безусловно, повреждает мой файл.
Я использовал следующий фрагмент для возобновления загрузки, поэтому надеялся, что поток возобновится там, где он остановил localStream.Искать(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 amp;amp; 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);
}
Комментарии:
1. ну, вы могли бы использовать range для загрузки порциями
public Download(HttpRange range = default, BlobRequestConditions conditions = null, bool rangeGetContentHash = false, CancellationToken cancellationToken = default);
Ответ №1:
Я провел для вас несколько тестов, в моем случае я использую текстовый файл для демонстрации ваших требований. Вы можете увидеть текстовый файл здесь . Как вы можете видеть, в строке 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-файл:
Пожалуйста, дайте мне знать, если у вас возникнут еще какие-либо вопросы.
Комментарии:
1. Это действительно многообещающе, я собираюсь его протестировать … спасибо, приятель
2. Привет @Henkie85, ваша проблема решена?