2010-02-24 10 views
0

В приложении ASP.NET я использую iTextSharp (в основном PdfStamper) для заполнения некоторого содержимого в формате PDF и отправки его пользователю. Следующий код в событие OnClick:Выход Response.Stream (PDF), потерянный Adobe Reader

PdfReader r = new PdfReader(
    new RandomAccessFileOrArray(Request.MapPath(compatiblePdf)), null 
); 

ps = new PdfStamper(r, Response.OutputStream); 
AcroFields af = ps.AcroFields; 

af.SetField("ContactInfo[0]", o.mallName); 
af.SetField("ClientName", string.Format("{0} {1}", c.firstName, c.lastName)); 
af.SetField("ClientEmail", c.emailAddress); 
ps.FormFlattening = true; 
Response.ContentType = "application/pdf"; 
Response.AddHeader("Content-Disposition", "attachment; filename=Form.pdf"); 
ps.Close(); 
Response.End(); 

Так, в основном, PdfReader получает файл, PdfStamper принимает PdfReader в качестве аргумента, и будет толкать его готовый PDF в Response.OutputStream.

Проблема заключается в том, что с помощью IE и Adobe Reader, если вы выберите «Открыть» в диалоговом окне файла, Adobe Reader выдает сообщение об ошибке «Файл не найден». Пользователи могут «Сохранить» файл просто отлично, и даже начать загрузку снова (нажатие «Открыть» снова по запросу), похоже, работает. Но на новой машине, которая никогда не загружала файл, Adobe Reader, похоже, неправильно использует файл между ним и временными файлами или любым другим IE.

Я могу только представить себе одну вещь прямо сейчас: Response.End(), должно быть, должно быть Response.Close() вместо этого, или, может быть, все это должно иметь Response.Flush() перед этим. Но я не знаю точно, что это не сделает проблему хуже, и мне сложно провести тестирование (потому что, как только вы загрузили файл один раз, ошибка не будет сброшена снова).

Возможно, это проблема? У меня что-то не так в заголовках? Или есть что-то еще, что я должен делать с объектами Response/PdfStamper?

ответ

5

Всякий раз, когда я заставляю содержание на пользователя, я следую за этот набор шагов для реагирования:

Response.Clear() 
Response.ClearHeaders() 
Response.Buffer = True 
Response.ContentType = "your mime type" 
Response.CacheControl = "public" 
Response.AddHeader("Pragma", "public") 
Response.AddHeader("Expires", "0") 
Response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0") 
Response.AddHeader("Content-Description", "Description of your content") 
Response.AddHeader("Content-Disposition", "attachment; filename=""somefile.pdf""") 

' Add your content to the buffer here 

Response.Flush() 
Response.End() 

Это, кажется, довольно хорошо на предотвращение всех «файл не найден» мусор.

EDIT: Для тех, кто заинтересован в том, что эти заголовки на самом деле означает:

  1. Pragma: public помогает кэш управления для обеспечения обратной совместимости с HTTP/1.0 запросы. Это гарантирует, что ваш запрос будет отправлен на сервер, даже если уже есть кешированный ответ.
  2. Expires: 0 - это интервал в секундах, через который истекает срок действия ответа. Установка в 0 немедленно отменяет ответ, помогая избежать устаревших кешей.
  3. Cache-control: must-revalidate сообщает кешу, что он должен подчиняться каждой вашей команде (т. Е. Он должен дать вам новый ответ, когда вы его попросите).
  4. Cache-control: post-check=0, pre-check=0: это интервал в секундах, в течение которого ответ должен быть проверен на свежесть после/до (соответственно), обслуживаемого содержимым. Установка на 0 принудительно проверяет свежесть ответа. (More at MSDN.)
  5. Остальные просто описывают контент, который вы хотите получить от пользователя. Указание «вложения» указывает браузеру предлагать файл в виде загрузки и не отображать его в строке.
+0

По какой причине это должно быть сделано? Это работает, но какая-то конкретная причина? – tHeSiD

+0

Я обновил сообщение тем, что мог запомнить или выкопать. –