Выгружаемый архив поврежден или имеет не верный формат

Рейтинг: 0Ответов: 1Опубликовано: 31.01.2023

Делаю выгрузку архива с бэка. На фронте его выгружаю, но он битый (не открывается).

Думал как-то не так данные пишу в архив, но нет. Дело не в этом. В примере ниже я помещаю в архив только один текстовый файл. Но и этот архив не открывается.

Также вес архива получается слишком маленьким. Что делаю не так ?

var response = new HttpResponseMessage(HttpStatusCode.OK);
        using (var ms = new MemoryStream())
        {
            using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
            {
                var entry = zipArchive.CreateEntry("file.txt");
            }
            ms.Position = 0;
            response.Content = new StreamContent(ms);
            response.Content.Headers.ContentLength = ms.Length;
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "Archive.zip"
            };
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
            return response;}

UPD. Кусок кода из работы:

var setting = Configuration.GetTypedSection<MicroSipSettings>("MicroSip");


        using (var memoryStream = new MemoryStream())
        {
            var response = new HttpResponseMessage(HttpStatusCode.OK);
            var filepaths = Directory.GetFiles(setting.DirMicroSip);
            using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
            {
                foreach (string filepath in filepaths)
                {
                    string filename = Path.GetFileName(filepath);
                    var entry = archive.CreateEntry(filename);
                    using (var file = File.OpenRead(Path.Combine(setting.DirMicroSip, filename)))
                    using (var entryStream = entry.Open())
                    {
                        await file.CopyToAsync(entryStream);
                    }
                }
                ZipArchiveEntry iniEntry = archive.CreateEntry(setting.NameIni);
                using (var sw = new StreamWriter(iniEntry.Open()))
                {
                    sw.WriteLine("[Settings]");
                    sw.WriteLine("accountId=1");
                    ...

                }
            }

            memoryStream.Position = 0;
            response.Content = new StreamContent(memoryStream);
            response.Content.Headers.ContentLength = memoryStream.Length;
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "Archive.zip"
            };
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
            return response;
        }

Ответы

▲ 1Принят

Дело в том, что вы уничтожаете MemoryStream до того как воспользуетесь им.

То есть вот здесь

return response;

следом неявно вызывается

memoryStream.Dispose();

И только после этого response долетает до адресата и начинает отдаваться на скачивание. В результате сервер ничего не может прочитать из закрытого потока чтобы отдать клиенту.

Исправьте

using (var memoryStream = new MemoryStream())

на просто

var memoryStream = new MemoryStream();

Вообще MemoryStream можно не диспозить, у него внутри ничего такого нет, что требует обязательного следования правилам работы с IDisposable.