Несоответствие содержимого FileResult-длины

#c# #http #.net-core #content-length #fileresult

#c# #http #.net-ядро #длина содержимого #файловый результат

Вопрос:

Привет, я использую код из этого поста в блоге :

https://blog.stephencleary.com/2016/11/streaming-zip-on-aspnet-core.html

Для того, чтобы передавать zip-файл в потоковом режиме .Сетевое ядро. Я заставил это работать, но поскольку я не добавил заголовок длины содержимого в ответ, когда я не загружаю zip-файл, он не будет показывать ход загрузки в Chrome. Поскольку я заранее знаю размер zip-файла, я действительно могу установить заголовок длины содержимого с помощью метода SetHeadersAndLog https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.internal.fileresultexecutorbase.setheadersandlog?view=aspnetcore-2.0

но когда я это делаю, у меня возникает следующая ошибка :

System.InvalidOperationException: Response Content-Length mismatch: too many bytes written (144144633 of 144144627) .

Есть идеи, почему ответ не такой длины, как zip-файл? Вот код для обслуживания файла:

      this._httpContext.Response.ContentType = "application/octet-stream";
            this._httpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
            this._httpContext.Response.ContentLength = estimatedFileSize;

            FileCallbackResult result = new FileCallbackResult(new MediaTypeHeaderValue("application/octet-stream"), estimatedFileSize, async (outputStream, _) =>
            {
                using (ZipArchive zip = new ZipArchive(outputStream, ZipArchiveMode.Create, false))
                {
                    foreach (string filepath in Directory.EnumerateFiles(existingDirectory.FullName, "*.*", SearchOption.AllDirectories))
                    {
                        string relativepath = filepath.Replace(existingDirectory.FullName   "\", string.Empty);

                        ZipArchiveEntry zipEntry = zip.CreateEntry(relativepath, CompressionLevel.Fastest);
                        using (Stream zipstream = zipEntry.Open())
                        {
                            using (Stream stream = new FileStream(filepath, FileMode.Open))
                            {
                                await stream.CopyToAsync(zipstream);
                            }
                        }
                    }
                }
            })
            {
                FileDownloadName = $"{package.FileName}.zip",
            };
  

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

1. Покажите, где вы заполняете estimatedFileSize .

2. @mxmissile У меня уже есть zip-файл на диске (который я создал тем же способом, что и здесь, с тем же уровнем сжатия) Я получаю его как FileInfo с помощью Directory.EnumerateFile(filename).firstordefault() затем я проверяю его длину.

3. Вы пробовали просто отправить этот файл вместо этого или воссоздать его заново? Разные библиотеки zip имеют разные уровни сжатия.

Ответ №1:

Вам нужно выполнить поиск потока обратно к началу.

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

1. это означает: основной поток. Искать(0, SeekOrigin.Begin);