“назовите” web pdf для лучшего сохранения имени файла по умолчанию в Acrobat?
-
02-07-2019 - |
Вопрос
Мое приложение генерирует PDF-файлы для использования пользователем.HTTP-заголовок "Content-Disposition" устанавливается, как указано выше здесь.Для этого значения установлено значение "встроенный;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
Решение
Частично проблема заключается в том, что соответствующие RFC 2183 на самом деле не указано, что делать с типом расположения "inline" и именем файла.
Кроме того, насколько я могу судить, единственным UA, который фактически использует имя файла для type=inline, является Firefox (см. тестовый пример).
Наконец, не очевидно, что API плагина действительно делает эту информацию доступной (возможно, кто-то, знакомый с API, сможет уточнить).
Тем не менее, я отправил указатель на этот вопрос сотруднику Adobe;может быть, нужные люди взглянут на это.
Похожие:смотрите попытку прояснить расположение содержимого в HTTP в черновик-решке-rfc2183-в-http -- это ранняя стадия работы, обратная связь приветствуется.
Обновить:Я добавил тестовый пример, что, по-видимому, указывает на то, что плагин Acrobat reader не использует заголовки ответов (в Firefox), хотя API плагина предоставляет к ним доступ.
Другие советы
Установите имя файла в ContentType ( Тип содержимого ) также хорошо.Это должно решить проблему.
context.Response.ContentType = "application/pdf; name=" + fileName;
// the usual stuff
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName);
После установки заголовка content-disposition также добавьте заголовок content-length, затем используйте binarywrite для потоковой передачи PDF-файла.
context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());
context.Response.BinaryWrite(fileBytes);
Как и ты, я много раз пытался заставить это сработать.В конце концов я отказался от этой идеи и просто выбрал обходной путь.
Я использую ASP.NET MVC Framework, поэтому я изменил свои маршруты для этого контроллера / действия, чтобы убедиться, что отправляемый PDF-файл является последней частью части местоположения URI (перед строкой запроса), и передаю все остальное в строке запроса.
Например:
Старый УРИ:
http://server/app/report/showpdf?param1=foo ¶m2=строка иимя файла=myreport.pdf
Новый URI:
http://server/app/report/showpdf/myreport.pdf?param1=foo ¶м2=бар
Результирующий заголовок выглядит точно так же, как вы описали (тип содержимого - application / pdf, расположение - встроенное, имя файла бесполезно является частью заголовка).Acrobat показывает его в окне браузера (диалог сохранения как отсутствует), а имя файла, которое автоматически заполняется, если пользователь нажимает кнопку Acrobat Сохранить, является именем отчета.
Несколько соображений:
Чтобы имена файлов выглядели прилично, в них не должно быть никаких экранированных символов (т. е. никаких пробелов и т.д.)...что немного ограничивает возможности.В этом случае мои имена файлов генерируются автоматически, и раньше в них были пробелы, которые отображались как '%20' в результирующем окне сохранения имени файла.Я просто заменил пробелы символами подчеркивания, и это сработало.
Это, безусловно, лучшее решение, но оно действительно работает.Это также означает, что у вас должно быть доступно имя файла, чтобы сделать его частью исходного URI, что может нарушить рабочий процесс вашей программы.Если оно в данный момент генерируется или извлекается из базы данных во время серверного вызова, генерирующего PDF-файл, вам может потребоваться переместить код, генерирующий имя файла, в javascript как часть отправки формы, или, если оно поступает из базы данных, выполнить быстрый вызов ajax для получения имени файла при создании URL, который приводит к получению встроенного PDF-файла.
Если вы берете имя файла из пользовательского ввода в форме, то оно должно быть проверено на отсутствие экранированных символов, которые будут раздражать пользователей.
Надеюсь, это поможет.
Попробуйте поместить имя файла в конец URL-адреса перед любыми другими параметрами.У меня это сработало.http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/
В ASP.NET 2.0 измените URL с
http://www. server.com/DocServe.aspx?DocId=XXXXXXX
Для
http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX
Это работает для Acrobat 8, и по умолчанию сохраняется имя файла now MySaveAsFileName.pdf
.
Однако вы должны ограничить допустимые символы в MySaveAsFileName
(никаких периодов и т.д.).
Апачи 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
.
Если вы используете asp.net, вы можете управлять именем файла PDF с помощью имени страницы (URL).Как писали другие пользователи, Acrobat - это немного s...при нажатии кнопки "Сохранить" выберите имя PDF-файла:он берет название страницы, удаляет расширение и добавляет ".pdf".Итак, /foo/bar/GetMyPdf.aspx выдает GetMyPdf.pdf.
Единственное решение, которое я нашел, - это управлять "динамическими" названиями страниц с помощью asp.net обработчика:
- создайте класс, реализующий IHttpHandler
- сопоставьте обработчик в web.config, ограниченный классом
Отображение 1:все страницы имеют общий радиус (MyDocument_):
<httpHandlers>
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Отображение 2:полностью свободное имя файла (требуется указать путь к папке):
<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
Вместо вложения вы можете попробовать встроенное:
Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");
Я использовал inline в предыдущем веб-приложении, которое генерировало выходные данные Crystal Reports в формате PDF и отправляло их пользователю в браузере.
Диалоговое окно загрузки файла (PDF) с возможностью сохранения и открытия
Моменты, которые нужно Запомнить:
- Возвращает поток с правильным размером массива из сервиса
- Считайте список байтов из потока с правильной длиной байта на основе длины потока.
- установите правильный тип содержимого
Вот код для чтения потока и открытия диалогового окна загрузки файла 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();
}
}
Я полагаю, что это уже упоминалось в той или иной форме, но я попытаюсь изложить это своими словами.
Вместо этого:
/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-адресе, я просто передаю запрошенный файл.(обратите внимание, что я не могу просто перенаправить на запрошенный файл - иначе я оказался бы в бесконечном цикле)
У вас всегда может быть две ссылки.Один, который открывает документ внутри браузера, а другой - для его загрузки (используя неправильный тип содержимого).Это то, что делает Gmail.
Для тех, кто все еще смотрит на это, я использовал найденное решение здесь и это сработало чудесно.Спасибо, Фабрицио!
Способ, которым я решил это (с помощью PHP), заключается в следующем:
Предположим, ваш URL-адрес следующий SomeScript.php?id=ID&data=DATA
и файл, который вы хотите использовать, это TEST.pdf
.
Измените URL-адрес на SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf
.
Важно, чтобы последним параметром было имя файла, которое вы хотите использовать Adobe ("EXT" может означать что угодно).Кстати, убедитесь, что в приведенной выше строке нет специальных символов.
Теперь, на вершине SomeScript.php
, добавить:
$_REQUEST = MakeFriendlyURI( $_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']);
Затем добавьте эту функцию в SomeScript.php
(или ваша библиотека функций):
function MakeFriendlyURI($URI, $ScriptName) {
/* Need to remove everything up to the script name */
$MyName = '/^.*'.preg_quote(basename($ScriptName)."/", '/').'/';
$Str = preg_replace($MyName,'',$URI);
$RequestArray = array();
/* Breaks down like this
0 1 2 3 4 5
PARAM1/VAL1/PARAM2/VAL2/PARAM3/VAL3
*/
$tmp = explode('/',$Str);
/* Ok so build an associative array with Key->value
This way it can be returned back to $_REQUEST or $_GET
*/
for ($i=0;$i < count($tmp); $i = $i+2){
$RequestArray[$tmp[$i]] = $tmp[$i+1];
}
return $RequestArray;
}//EO MakeFriendlyURI
Сейчас $_REQUEST
(или $_GET
если вы предпочитаете) доступен как обычный $_REQUEST['id']
, $_REQUEST['data']
, и т.д.
И Adobe будет использовать желаемое вами имя файла в качестве сохраняемого по умолчанию имени или информации по электронной почте, когда вы отправите его встроенным.
Я был перенаправлен сюда, потому что у меня такая же проблема.Я также попробовал обходной путь Троя Ховарда, но, похоже, он не работает.
Подход, который я применил в этом случае, заключается в ТОМ, чтобы БОЛЬШЕ НЕ использовать объект ответа для записи файла "на лету".Поскольку PDF-файл уже существует на сервере, я перенаправил свою страницу, указывающую на этот PDF-файл.Отлично работает.
http://forums.asp.net/t/143631.aspx
Я надеюсь, что мое расплывчатое объяснение натолкнуло вас на какую-то идею.
Кредиты для Вивек.
Nginx
location /file.pdf
{
# more_set_headers "Content-Type: application/pdf; name=save_as_file.pdf";
add_header Content-Disposition "inline; filename=save_as_file.pdf";
alias /var/www/file.pdf;
}
Проверьте с помощью
curl -I https://example.com/file.pdf
Firefox 62.0b5 (64-разрядный):ОК.
Chrome 67.0.3396.99 (64-разрядная версия):ОК.
IE 11:Без комментариев.
Попробуйте это, если ваш исполняемый файл "get.cgi"
http://server ,org/get.cgi/filename.pdf?файл=filename.pdf
Да, это полное безумие.На сервере нет файла с именем "filename.pdf", вообще есть каталог под исполняемым файлом get.cgi.
Но, кажется, это работает.Сервер игнорирует filename.pdf, а программа чтения PDF игнорирует "get.cgi".
Dan