C # большая загрузка файлов, возобновляемая из хранилища больших двоичных объектов Azure

#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, ваша проблема решена?