Создание PDF, ошибка с IE и HTTPS

Я передаю PDF в браузер в ASP.NET 2.0. Это работает во всех браузерах через HTTP и обо всех браузерах except IE поверх HTTPS. Насколько я знаю, это работало (за последние 5 лет или около того) во всех версиях IE, но наши клиенты только недавно начали сообщать о проблемах. Я подозреваю, что параметр безопасности Не сохранять зашифрованные страницы на диск по умолчанию был отключен, а в какой-то момент стал включен по умолчанию ( "Свойства обозревателя → Дополнительно → Безопасность" ). Отключение этой функции помогает, как работа, но не является жизнеспособным в качестве долгосрочного решения.

Сообщение об ошибке, которое я получаю:

Internet Explorer не может загрузить OutputReport.aspx с сайта www.sitename.com.

Internet Explorer не смог открыть этот интернет-сайт. Запрошенный сайт либо недоступен, либо не может быть найден. Повторите попытку позже.

Инструментом, используемым для создания PDF, является ActiveReports из DataDynamics. Как только PDF создается, вот код для его отправки:

Response.ClearContent()
Response.ClearHeaders()
Response.AddHeader("cache-control", "max-age=1")
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "attachment; filename=statement.pdf")
Response.AddHeader("content-length", mem_stream.Length.ToString)
Response.BinaryWrite(mem_stream.ToArray())
Response.Flush()
Response.End()  

Примечание. Если я не укажу явным образом контроль кеша, тогда .NET отправит от моего имени кеш-кеш, поэтому я попытался настроить кеш-контроль для: private или public или maxage = #, но ни один из них не выглядит работа.

Вот твист: когда я запускаю Fiddler для проверки заголовков ответов, все работает нормально. Я получаю следующие заголовки:

HTTP/1.1 200 OK
Cache-Control: max-age = 1
Дата: ср, 29 июл 2009 17:57:58 GMT
Content-Type: application/pdf
Сервер: Microsoft-IIS/6.0
MicrosoftOfficeWebServer: 5.0_Pub
X-Powered-By: ASP.NET
X-AspNet-версия: 2.0.50727
content-disposition: attachment; filename = statement.pdf
Content-Encoding: gzip
Vary: Accept-Encoding
Передача-кодирование: chunked

Как только я выключу Fiddler и повторю попытку, он снова терпит неудачу. Еще одна вещь, которую я заметил, заключается в том, что при запуске Fiddler я получаю Проблема с предупреждением об этом сертификате безопасности, и я должен нажать Перейти на этот сайт (не рекомендуется), чтобы пройти. Когда Fiddler выключен, я не сталкиваюсь с этим предупреждением о безопасности, и он сразу же не работает.

Мне любопытно, что происходит между Fiddler и браузером, так что это работает, когда Fiddler работает, но ломается, когда это не так, но что еще более важно, у кого-нибудь есть идеи, как я могу изменить свой код, поэтому потоковые PDF файлы в IE будут работать без внесения изменений в клиентскую машину?

Обновление: Проблемы с Fiddler решены, большое спасибо EricLaw, поэтому теперь он ведет себя последовательно (сломанный, с или без Fiddler работает).

На основе поиска Google, похоже, есть много сообщений об этой же проблеме по всему Интернету, каждая из которых имеет свою собственную комбинацию заголовков ответов, которые, как представляется, устраняют проблему для их отдельных случаев. Я пробовал многие из этих предложений, включая добавление даты ETag, LastModified, удаление заголовка Vary (с использованием Fiddler) и десятки комбинаций заголовков Cache-Control и/или Pragma. Я попробовал "Content-Transfer-Encoding: binary", а также "application/force-download" для ContentType. Пока ничего не помогло. Есть несколько Microsoft KB статьи, все из которых указывают, что Cache-Control: no-cache является виновником. Любые другие идеи?

Обновление: Кстати, для полноты эта же проблема возникает и с выводами Excel и Word.

Обновление: Прогресс не достигнут. Я отправил файл SAS из Fiddler в EricLaw, и он смог воспроизвести проблему при отладке IE, но пока нет решений. Bounty истекает...

Ответ 1

Спустя две недели на дикой гусиной погоне я не смог найти комбинацию изменений кода, которая позволит использовать этот метод потоковой передачи документов PDF, Excel или Word, когда " Не сохранять зашифрованные страницы на диск '.

Microsoft заявила, что это поведение разработано в нескольких статьях KB и частных электронных письмах. Похоже, что когда опция Не сохранять зашифрованные страницы на диск 'включена, IE ведет себя правильно и делает то, что ему говорят. Этот пост - лучший ресурс, который я нашел до сих пор, что объясняет, почему этот параметр будет включен, а также плюсы и минусы:

  

"При работе с соединениями SSL (HTTPS) играет роль" Не сохранять зашифрованные страницы на диск ". Подобно тому, как веб-сервер может отправлять информацию о том, как кэшировать файл, можно в основном устанавливают Internet Explorer, чтобы не сохранять файлы в кеш при соединении SSL (HTTPS), независимо от того, что веб-сервер советует вам.

         

В чем заключается причина включения этой функции, безопасность - причина номер один, почему функция включена. Страницы не сохраняются в кэше временных файлов Интернета.

         

В чем недостаток? Медленная производительность, так как в кеш ничего не сохраняется, даже каждый раз, когда изображение размером в 1 байт, используемое десятками раз на странице, должно появляться с веб-сервера. Хуже того, некоторые действия пользователя могут потерпеть неудачу, так как загруженные файлы будут удалены, а представленная ошибка или открытие PDF-документов не смогут назвать несколько сценариев."

  

Лучшее решение, которое мы можем найти на данном этапе, - это сообщить нашим клиентам и пользователям, что существуют альтернативы для использования этого параметра:

  

"Использовать папку" Empty Temporary Internet Files "при закрытии браузера". Каждый раз, когда браузер закрывается, все файлы будут удалены из кеша, предполагая, что нет блокировки файла из другого экземпляра браузера или какого-либо внешнего приложения.

         

Перед использованием ' нужно много внимания рассмотреть, не сохраняя зашифрованные страницы на диске. Похоже на отличную функцию безопасности, но результаты использования этой функции могут привести к тому, что вызовы вашей службы поддержки повысятся для сбоев загрузки или низкой производительности ".

  

Ответ 2

Недопустимый заголовок Cache-Control. Он должен быть Cache-Control: max-age = 1 с тире в середине. Попытайтесь исправить это, прежде всего, чтобы узнать, имеет ли значение значение.

Как правило, я бы сказал, что наиболее вероятным виновником является ваш заголовок Vary, поскольку такие заголовки часто вызывают проблемы с кешированием в IE: http://blogs.msdn.com/ieinternals/archive/2009/06/17/9769915.aspx. Возможно, вам захочется добавить в заголовки ответов ETAG.

Fiddler не должен влиять на кешируемость (если вы не написали правила), и похоже, что вы говорите, что это так, что предполагает, что, возможно, есть какая-то временная проблема.

> Не сохраняйте зашифрованные страницы для параметра защиты диска, которое по умолчанию отключено.

Эта опция по умолчанию отключена (в IE6, 7 и 8), хотя ИТ-администраторы могут включить ее с помощью групповой политики, и некоторые крупные компании делают это.

Кстати, причина, по которой вы видите ошибку сертификата при запуске Fiddler, заключается в том, что вы не решили доверять корневому сертификату Fiddler; см. http://www.fiddler2.com/fiddler/help/httpsdecryption.asp для получения дополнительной информации по этой теме.

Ответ 3

У меня была аналогичная проблема с файлами PDF, которые я хотел передать. Даже с Response.ClearHeaders() я видел заголовки Pragma и Cache-Control, добавленные во время выполнения. Решение состояло в том, чтобы очистить заголовки в IIS (щелкните правой кнопкой мыши → Свойства на странице, загружая PDF файл, затем вкладку "Http-заголовки" ).

Ответ 4

Мы столкнулись с подобной проблемой долгое время назад - мы сделали это (это Java EE). В конфигурации веб-приложения мы добавим

<mime-mapping>
    <extension>PDF</extension>
    <mime-type>application/octet-stream</mime-type>
</mime-mapping>

Это приведет к тому, что любой pdf файл, отправляемый из вашего веб-приложения, будет загружен вместо браузера, пытающегося выполнить рендеринг.

EDIT: похоже, что вы его передаете. В этом случае вы будете использовать mime-тип как application/octet-stream в своем коде, а не в конфиге. Итак, вместо

Response.ContentType = "application/pdf"

вы будете использовать

Response.ContentType = "application/octet-stream"

Ответ 5

Я обнаружил, что это, похоже, работает для меня:

Dim browser As System.Web.HttpBrowserCapabilities = Request.Browser
If (browser.Browser = "IE") Then
  Response.AppendHeader("cache-control", "private") ' ie only
Else
  Response.AppendHeader("cache-control", "no-cache") ' all others (FF/Chrome tested)
End If

Ответ 6

SOLVED: Это проблема IE, а не приложение... исправить это следующим образом: http://support.microsoft.com/kb/323308 Он работает идеально для меня, после длительного использования.

ATT: Mr.Dark

Ответ 7

Какая версия IE? Я помню, что Microsoft выпустила исправление для IE6 для этой проблемы. Надеюсь, что это полезно?

Ответ 9

попытайтесь отключить сжатие gzip.

Ответ 10

Добавьте его сюда, надеясь, что кто-то может найти это полезным, а не через ссылки.

Вот мой код

    byte[] bytes = // get byte array from DB

    Response.Clear();
    Response.ClearContent();
    Response.ClearHeaders();
    Response.Buffer = true;

    // Prevent this page from being cached.
    //  NOTE: we cannot use the CacheControl property, or set the PRAGMA header value due to a flaw re: PDF/SSL/IE
    Response.Expires = -1; 

    Response.ContentType = "application/pdf";
    // Specify the number of bytes to be sent
    Response.AppendHeader("content-length", bytes.Length.ToString());

    Response.BinaryWrite(bytes);    

            // Wrap Up
    Response.Flush();
    Response.Close();
    Response.End();

Ответ 11

Как и OP, я несколько дней царапал себе голову, пытаясь заставить это работать, но я сделал это в конце, поэтому я решил поделиться своей "комбинацией" заголовков:

            if (System.Web.HttpContext.Current.Request.Browser.Browser == "InternetExplorer"
                && System.Web.HttpContext.Current.Request.Browser.Version == "8.0")
            {
                System.Web.HttpContext.Current.Response.Clear();
                System.Web.HttpContext.Current.Response.ClearContent();
                System.Web.HttpContext.Current.Response.ClearHeaders();
                System.Web.HttpContext.Current.Response.ContentType = "application/octet-stream";

                System.Web.HttpContext.Current.Response.AppendHeader("Pragma", "public");
                System.Web.HttpContext.Current.Response.AppendHeader("Cache-Control", "private, max-age=60");
                System.Web.HttpContext.Current.Response.AppendHeader("Content-Transfer-Encoding", "binary");

                System.Web.HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + document.Filename);
                System.Web.HttpContext.Current.Response.AddHeader("content-length", document.Data.LongLength.ToString());

                System.Web.HttpContext.Current.Response.BinaryWrite(document.Data);
            }

Надеюсь, что кто-то кого-нибудь спасет от боли!

Ответ 12

У меня возникла аналогичная проблема с попыткой потока PDF через SSL и поместить это внутри iframe или объекта. Я обнаружил, что моя страница aspx будет перенаправляться на незащищенную версию URL-адреса, и браузер блокирует ее.

Я обнаружил, что переход с ASPX-страницы на обработчик ASHX фиксировал мою проблему перенаправления.