"имя" веб-PDF для лучшего сохранения файла по умолчанию в Acrobat - PullRequest
42 голосов
/ 30 сентября 2008

Мое приложение генерирует PDF-файлы для использования пользователем. HTTP-заголовок "Content-Disposition" установлен так, как указано здесь . Для него установлено значение «inline; filename = foo.pdf», которого должно быть достаточно для того, чтобы Acrobat предоставил «foo.pdf» в качестве имени файла при сохранении pdf.

Однако после нажатия кнопки «Сохранить» во встроенном в браузер Acrobat именем по умолчанию для сохранения будет не это имя файла, а URL-адрес с косой чертой, измененный на подчеркивание. Огромный и безобразный. Есть ли способ повлиять на это имя файла по умолчанию в Adobe?

В URL есть строка запроса, и это не подлежит обсуждению. Это может быть важно, но добавление «& foo = / title.pdf» в конец URL не влияет на имя файла по умолчанию.

Обновление 2: я пробовал оба

content-disposition  inline; filename=foo.pdf
Content-Type         application/pdf; filename=foo.pdf

и

content-disposition  inline; filename=foo.pdf
Content-Type         application/pdf; name=foo.pdf

(подтверждено через Firebug) К сожалению, ни один из них не работал.

Пример URL-адреса

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true

, что соответствует сохранению Acrobat по умолчанию в качестве имени файла

http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf

Обновление 3: Джулиан Решке привносит реальное понимание и строгость в этот случай. Пожалуйста, подтвердите его ответ. Похоже, что это не работает в FF (https://bugzilla.mozilla.org/show_bug.cgi?id=433613) и IE, но работает в Opera, Safari и Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf

Ответы [ 16 ]

10 голосов
/ 21 марта 2009

Часть проблемы заключается в том, что соответствующий RFC 2183 на самом деле не указывает, что делать с типом расположения «inline» и именем файла.

Кроме того, насколько я могу судить, единственным UA, который фактически использует имя файла для type = inline, является Firefox (см. test case ).

Наконец, не очевидно, что API плагина на самом деле делает эту информацию доступной (может, кто-нибудь, знакомый с API, может уточнить).

При этом я отправил указатель на этот вопрос сотруднику Adobe; может быть, правильные люди будут смотреть.

Связано: см. Попытку разъяснить расположение содержимого в HTTP в draft-reschke-rfc2183-in-http - это ранняя работа в процессе, обратная связь приветствуется.

Обновление: я добавил контрольный пример , который, похоже, указывает на то, что плагин Acrobat Reader не использует заголовки ответа (в Firefox), хотя API плагина предоставляет к ним доступ.

9 голосов
/ 04 декабря 2008

Как и вы, я пытался и пытался заставить это работать. В конце концов я отказался от этой идеи и просто выбрал обходной путь.

Я использую ASP.NET MVC Framework, поэтому я изменил свои маршруты для этого контроллера / действия, чтобы убедиться, что обслуживаемый файл PDF является последней частью части расположения URI (перед строкой запроса), и передать все остальное в строке запроса.

Например:

Старый URI:

http://server/app/report/showpdf?param1=foo&param2=bar&filename=myreport.pdf

Новый URI:

http://server/app/report/showpdf/myreport.pdf?param1=foo&param2=bar

Полученный заголовок выглядит точно так же, как вы описали (тип контента - application / pdf, расположение - встроенное, имя файла - бесполезная часть заголовка) Acrobat показывает его в окне браузера (без сохранения как диалоговое окно), и имя файла, которое автоматически заполняется, если пользователь нажимает кнопку «Acrobat Save», является именем файла отчета.

Несколько соображений:

Чтобы имена файлов выглядели прилично, в них не должно быть экранированных символов (то есть без пробелов и т. Д.) ... что немного ограничивает. В этом случае мои имена файлов генерируются автоматически, и раньше в них были пробелы, которые отображались как '% 20' в результирующем имени файла диалога сохранения. Я просто заменил пробелы подчеркиванием, и это сработало.

Это никоим образом не лучшее решение, но оно работает. Это также означает, что вам нужно иметь доступное имя файла, чтобы сделать его частью исходного URI, что может мешать работе вашей программы. Если он в настоящее время генерируется или извлекается из базы данных во время вызова на стороне сервера, который генерирует PDF, вам может потребоваться переместить код, который генерирует имя файла, в javascript как часть отправки формы или если он исходит из базы данных, сделайте его быстрый вызов ajax для получения имени файла при создании URL, который приводит к встроенному PDF.

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

Надеюсь, это поможет.

9 голосов
/ 30 сентября 2008

Установите имя файла в ContentType . Это должно решить проблему.

context.Response.ContentType = "application/pdf; name=" + fileName;
// the usual stuff
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName);

После установки заголовка расположения содержимого также добавьте заголовок длины содержимого, а затем используйте двоичный файл для потоковой передачи PDF.

context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());
context.Response.BinaryWrite(fileBytes);
5 голосов
/ 02 декабря 2011

Попробуйте поместить имя файла в конце URL-адреса перед любыми другими параметрами. Это сработало для меня. http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/

4 голосов
/ 28 июля 2011

Apache's mod_rewrite может решить эту проблему.

У меня есть веб-сервис с конечной точкой на /foo/getDoc.service. Конечно, Acrobat сохранит файлы как getDoc.pdf. Я добавил следующие строки в apache.conf:

LoadModule     RewriteModule         modules/mod_rewrite.so
RewriteEngine  on
RewriteRule    ^/foo/getDoc/(.*)$    /foo/getDoc.service     [P,NE]

Теперь, когда я запрашиваю /foo/getDoc/filename.pdf?bar&qux, он внутренне переписывается в /foo/getDoc.service?bar&qux, поэтому я попадаю на правильную конечную точку веб-службы, но Acrobat считает, что мой файл будет сохранен как filename.pdf.

4 голосов
/ 26 декабря 2010

В ASP.NET 2.0 измените URL с

http://www. server.com/DocServe.aspx?DocId=XXXXXXX

до

http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX

Это работает для Acrobat 8, и имя файла SaveAs по умолчанию теперь MySaveAsFileName.pdf.

Однако вы должны ограничить разрешенные символы в MySaveAsFileName (без точек и т. Д.).

2 голосов
/ 22 мая 2009

Если вы используете asp.net, вы можете контролировать имя файла pdf через имя файла страницы (url). Как писали другие пользователи, Acrobat немного ... когда выбирает имя файла pdf при нажатии кнопки «Сохранить»: он берет имя страницы, удаляет расширение и добавляет «.pdf». Так /foo/bar/GetMyPdf.aspx выдает GetMyPdf.pdf.

Единственное решение, которое я нашел, - это управление "динамическими" именами страниц с помощью обработчика asp.net:

  • создать класс, который реализует IHttpHandler
  • сопоставить обработчик в web.config, привязанный к классу

Mapping1: все страницы имеют общее основание (MyDocument _):

<httpHandlers>  
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>

Mapping2: полностью бесплатное имя файла (нужна папка в пути):

<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>

Несколько советов здесь (PDF-файл динамически создается с использованием iTextSharp):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html

1 голос
/ 18 декабря 2010

Диалог загрузки файла (PDF) с возможностью сохранения и открытия

Очки для запоминания:

  1. Обратный поток с правильным размером массива из службы
  2. Считать байтовую последовательность из потока с правильной длиной байта на основе длины потока.
  3. установить правильный тип содержимого

Вот код для потока чтения и откройте диалог загрузки файла для файла PDF

private void DownloadSharePointDocument()
{
    Uri uriAddress = new Uri("http://hyddlf5187:900/SharePointDownloadService/FulfillmentDownload.svc/GetDocumentByID/1/drmfree/");
    HttpWebRequest req = WebRequest.Create(uriAddress) as HttpWebRequest;
    // Get response   
    using (HttpWebResponse httpWebResponse = req.GetResponse() as HttpWebResponse)
    {
        Stream stream = httpWebResponse.GetResponseStream();
        int byteCount = Convert.ToInt32(httpWebResponse.ContentLength);
        byte[] Buffer1 = new byte[byteCount];
        using (BinaryReader reader = new BinaryReader(stream))
        {
            Buffer1 = reader.ReadBytes(byteCount);
        }
        Response.Clear();
        Response.ClearHeaders();
        // set the content type to PDF 
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "attachment;filename=Filename.pdf");
        Response.Buffer = true;
        Response.BinaryWrite(Buffer1);
        Response.Flush();
       // Response.End();
    }
}
1 голос
/ 14 мая 2009

Я считаю, что это уже упоминалось в той или иной форме, но я постараюсь изложить это своими словами.

Вместо этого:

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true

Я использую это:

/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1

Вместо того, чтобы "экспортировать" обработать запрос, когда приходит запрос, я смотрю в URL для GeneratePDF = 1. Если найден, я запускаю любой код, выполняемый в «экспорте», вместо того, чтобы позволить моей системе пытаться искать и обслуживать PDF-файл в расположении /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf. Если GeneratePDF не найден в URL, я просто передаю запрошенный файл. (обратите внимание, что я не могу просто перенаправить на запрошенный файл - иначе я бы оказался в бесконечном цикле)

1 голос
/ 30 сентября 2008

Вместо вложения вы можете попробовать встроенный:

Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");

Я использовал inline в предыдущем веб-приложении, которое генерировало вывод Crystal Reports в PDF и отправлял его пользователю в браузере.

...