Как мне увеличить размер облачного файла хранилища файлов Azure, прежде чем я узнаю размер файла?

#stream #zip #cloud #azure-storage #azure-storage-files

#поток #zip #облако #azure-хранилище #azure-storage-files

Вопрос:

Я использую хранилище файлов Azure для хранения некоторых файлов, и я хочу создать zip-файл, содержащий некоторые из этих файлов, на том же общем ресурсе Azure.

Пока это мой код:

 private void CreateZip(CloudFileDirectory directory) {

    if (directory == null) throw new ArgumentNullException(nameof(directory));

    var zipFilename = $"{directory.Name}.zip";

    var zip = directory.GetFileReference(zipFilename);
    if (!zip.Exists()) { 

        zip.Create(0);  // <-- I don't know what size its gonna be!!

        using (var zipStream = zip.OpenWrite(null))
        using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) {

            foreach (var file in directory.ListFilesAndDirectories().OfType<CloudFile>()) {
                if (file.Name.Equals(zipFilename, StringComparison.InvariantCultureIgnoreCase))
                    continue;                        

                using (var fileStream = file.OpenRead()) {

                    var entry = archive.CreateEntry(file.Name);
                    using (var entryStream = entry.Open())
                        fileStream.CopyTo(entryStream); // <-- exception is thrown
                }
            }
        }
    }
}
  

В строке zip.Create(0); это создает пустой файл. Затем я продолжаю использовать эту ссылку на файл для создания zip-файла и добавляю в него материал, но когда он попадает в fileStream.CopyTo(entryStream); него, он выдает исключение с этим сообщением:

 The remote server returned an error: (416) The range specified is invalid for the current size of the resource.
  

Предположительно, потому что размер файла равен 0, и он не может автоматически увеличить размер.

Я могу создать файл с int.MaxValue помощью, но тогда я получаю файл размером 2 ГБ. Я даже не могу определить размер файла, который я добавляю к достижению, и изменить размер файла, чтобы увеличить его на эту величину, потому что это zip, и он будет сжимать и изменять размер файла.

Как мне это сделать?

Ответ №1:

Эта проблема больше связана с System.IO.Compression. Я переписал ваш код, пожалуйста, используйте вместо этого поток памяти, как в следующем коде. На моей стороне это работает нормально. Надеюсь, это может дать вам несколько советов.

        public static void CreateZip(CloudFileDirectory directory)
        {

            if (directory == null) throw new ArgumentNullException(nameof(directory));

            var zipFilename = $"{directory.Name}.zip";          
            var zip = directory.GetFileReference(zipFilename);
            if (!zip.Exists())
            {

                //zip.Create(600000);  // <-- I don't know what size its gonna be!!

                using (var memoryStream = new MemoryStream())
                {
                    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                    {

                        foreach (var file in directory.ListFilesAndDirectories().OfType<CloudFile>())
                        {
                            if (file.Name.Equals(zipFilename, StringComparison.InvariantCultureIgnoreCase))
                                continue;

                            using (var fileStream = file.OpenRead())
                            {

                                var entry = archive.CreateEntry(file.Name, CompressionLevel.Optimal);
                                using (var entryStream = entry.Open())
                                {

                                    fileStream.CopyTo(entryStream); // <-- exception is thrown
                                }

                            }
                        }
                    }
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    zip.UploadFromStream(memoryStream);

                }

            }
        }
  

Комментарии:

1. На самом деле я пытался использовать поток памяти, но не смог заставить его работать, и, глядя на ваш код, я думаю, это потому, что я забыл сбросить положение потока обратно на 0… спасибо за вашу помощь!

2. Знаете ли вы, возможно ли (как?) запустить UploadFromStream в начале, Чтобы мы непрерывно загружали поток, пока записываем в foreach него файлы? Я застрял, пытаясь разобраться в этом!