#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
него файлы? Я застрял, пытаясь разобраться в этом!