Я генерирую некоторый контент JSON, а затем выполняю GZipping этот контент перед возвратом gzipped контента пользователю из действия контроллера MVC.
Генерация контента и gzipping работает правильно, какЯ могу вывести сгенерированный файл на диск, а затем я могу открыть этот файл с помощью GZip.Однако при возврате содержимого в браузер содержимое было повреждено.
Я пробовал несколько разных подходов к возврату содержимого в браузер, например
return File(byte[], "application/gzip");
return new FileStreamResult(stream, "application/gzip")
. А такжезапись непосредственно в Response с использованием методов BinaryWrite () и WriteFile ()
Независимо от того, что я делаю, файл, который я получаю в браузере, поврежден.
Этот код показывает способ, которым яВ настоящее время я пытаюсь вернуть содержимое файла.
// This line writes my content byte[] array to disk. This file when opened with gzip works fine.
System.IO.File.WriteAllBytes(@"C:\temp\test.vcp", result.FileBytes);
// Writing out the byte array to the Response results in a corrupt file. I have also attempted to Response.WriteFile(@"C:\temp\test.vcp") which also results in a corrupt file.
Response.Clear();
Response.ContentType = "application/gzip";
Response.AppendHeader("Content-Disposition", cd.ToString());
Response.AddHeader("Content-Length", result.FileBytes.Length.ToString());
Response.BinaryWrite(result.FileBytes);
Response.Flush();
Response.Close();
Response.End();
Поскольку созданный мной файл может быть записан на диск и может быть прочитан с помощью Gzip, но файл, полученный браузером, поврежден, я уверен,что мое создание файла в порядке.Но каким-то образом после записи файла в Response он поврежден.
Я действительно задавался вопросом, может быть, какой-то HTTPHandler манипулирует результатом, но я не добавил никаких обработчиков (которые я вижу).
Я в настоящее время запускаю приложение локально через IISExpress.Как я могу проверить, какие HttpHandlers / HttpModules применяются к конвейеру?
В конечном итоге я ожидаю получить в браузере тот же файл, что записан на диск.
Для справки, мой сгенерированныйсодержимое имеет длину 132 байта, но браузер получает 216 байтов.Я заметил, что, глядя на структуру байтов полученных данных, в контенте есть повторяющийся шаблон из 3 байтов со значениями 239, 191, 189. Это выглядит почти так, как будто результирующий байтовый массив был заполнен или дополнен этими данными.3 байта.
РЕДАКТИРОВАТЬ
Вот автономный метод действий, который продемонстрировал проблему.
[HttpGet]
public void GetFile()
{
byte[] text = Encoding.ASCII.GetBytes(@"{""PetName"":""Doggy McDocFace"",""OwnerName"":""Kurt""}");
byte[] compressed = Compress(text);
var cd = new System.Net.Mime.ContentDisposition
{
// for example foo.bak
FileName = "ExampleFile.vcp",
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = true,
};
System.IO.File.WriteAllBytes(@"C:\temp\ExampleFile.vcp", compressed);
Response.Clear();
Response.ContentType = "application/gzip";
Response.AppendHeader("Content-Disposition", cd.ToString());
Response.AddHeader("Content-Length", compressed.Length.ToString());
Response.BinaryWrite(compressed);
Response.Flush();
Response.Close();
Response.End();
}
public byte[] Compress(byte[] raw)
{
using (var memory = new MemoryStream())
{
using (var gzip = new GZipStream(memory, CompressionMode.Compress, true))
{
gzip.Write(raw, 0, raw.Length);
}
return memory.ToArray();
}
}
Здесь я подделываю мой JSON-контент,а затем сжимая его.Файл, записанный на диск, работает нормально, и его можно открыть с помощью моего приложения GZip (я использую 7-zip).Однако файл, полученный браузером, поврежден.7-zip не может распознать его как файл gzip.
РЕДАКТИРОВАТЬ 2
Так что (благодаря @Will) выглядит, что содержимое при записи в Response падаетфол кодировки UTF-8.Я не могу понять, как, хотя, как в моем примере выше, я использую Encoding.ASCII.GetBytes (), чтобы преобразовать мою строку в массив byte [].
Я попытался установить
Response.Charset = Encoding.ASCII.EncodingName;
Response.ContentEncoding = Encoding.ASCII;
Но это все равно не приводит к загрузке действительного файла.
Редактировать 3
Я сузил проблему до шифрования GZipданные.Если я не зашифрую данные, то текстовый файл загружается нормально.Однако шифрование массива byte [] и последующая запись этого массива byte [] в Repsonse приводят к проблемам с кодировкой UTF-8.Любые байты со значением более 127 повреждены 3 байтами, о которых я упомяну далее.Я не могу понять, почему Ответ обрабатывает эти зашифрованные данные таким образом.Я предполагаю, что когда массив Byte [] представляет собой простой текст в виде массива byte [], тогда это обрабатывается нормально.Как только это будет правильный массив byte [], т. Е. Не просто строка в виде массива byte [], тогда в Response будет происходить другое преобразование кодировки.