“Nome” pdf web para um melhor padrão de salvamento nome do arquivo no Acrobat?
-
02-07-2019 - |
Pergunta
Meu aplicativo gera PDFs para consumo do usuário. O "Content-Disposition" http cabeçalho é definido como mencionado aqui . Isso é definido para "inline; filename = foo.pdf"., Que deve ser suficiente para Acrobat para dar "foo.pdf", como o nome do arquivo ao salvar o pdf
No entanto, ao clicar no botão "Salvar" no Acrobat incorporado-browser, o nome padrão para salvar não é esse nome, mas em vez disso o URL com barras alterados para sublinhados. Enorme e feio. Existe uma maneira de afetar esse nome de arquivo padrão no Adobe?
Não é uma string de consulta nos URLs, e isso não é negociável. Isto pode ser significativo, mas a adição de um "& foo = / title.pdf" ao final da URL não afeta o nome de arquivo padrão.
Update 2: Eu tentei tanto
content-disposition inline; filename=foo.pdf
Content-Type application/pdf; filename=foo.pdf
e
content-disposition inline; filename=foo.pdf
Content-Type application/pdf; name=foo.pdf
(tal como comprovado nos Firebug) Infelizmente, não funcionou.
Uma amostra de URL é
/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true
que se traduz em um padrão Acrobat salvar como nome de arquivo
http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf
Update 3: Julian Reschke traz uma visão real e rigor a este caso. Por favor upvote sua resposta. Este parece ser quebrado em FF ( https://bugzilla.mozilla.org/show_bug. cgi? id = 433613 ) e IE, mas o trabalho em Opera, Safari e Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf
Solução
Parte do problema é que o relevante RFC 2183 realmente não estado que a ver com a disposição de tipo "inline" e um nome de arquivo.
Além disso, tanto quanto eu posso dizer, a única UA que usa realmente o nome do arquivo para o tipo = linha é Firefox (veja caso de teste ).
Finalmente, não é óbvio que o plugin API realmente faz com que a informação disponível (talvez someboy familiarizado com a API pode elaborar).
Dito isto, eu enviou um ponteiro para esta pergunta a uma pessoa Adobe; talvez as pessoas certas irá dar uma olhada.
relacionadas: veja tentativa de esclarecer Content-Disposition em HTTP em projecto-Reschke-rfc2183-in-http -. este é um trabalho mais cedo em andamento, o feedback apreciado
Update: Eu adicionei um teste caso , o que parece indicar que o leitor Acrobat plugin não usar os cabeçalhos de resposta (no Firefox), embora a API plug-in fornece acesso a eles.
Outras dicas
Defina o nome do arquivo na ContentType também. Isto deve resolver o problema.
context.Response.ContentType = "application/pdf; name=" + fileName;
// the usual stuff
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName);
Depois de definir cabeçalho Content-Disposition, também adicionar cabeçalho de comprimento de conteúdo, em seguida, usar BinaryWrite para transmitir o PDF.
context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());
context.Response.BinaryWrite(fileBytes);
Como você, eu tentei e tentei chegar a este trabalho. Finalmente desisti dessa idéia, e apenas optou por uma solução alternativa.
Eu estou usando ASP.NET MVC Framework, então eu modifiquei meus rotas para esse controle / ação para certificar-se de que o arquivo PDF servido é a última parte da porção localização da URI (antes da string de consulta), e passar tudo o resto na cadeia de consulta.
Por exemplo:
Old URI:
http: // servidor / app / report / showpdf param1 = foo & param2 = bar & filename = myreport.pdf
New URI:
http: // servidor / app / report / showpdf / MeuRelatório. pdf? param1 = foo & param2 = bar
O cabeçalho resultante parece exatamente como o que você descreveu (tipo de conteúdo é application / pdf, disposição está em linha, filename é inutilmente parte do cabeçalho). Acrobat mostra-lo na janela do navegador (sem diálogo Salvar como) e o nome do arquivo que é preenchida automaticamente se um usuário clica no botão Acrobat Save é o nome do arquivo de relatório.
Algumas considerações:
Para que os nomes de arquivos que olhar decente, eles devem não tem nenhum caracteres de escape (isto é, sem espaços, etc) ... que é um pouco limitante. Meus nomes de arquivos são gerados automaticamente neste caso, e antes de espaços tiveram neles, que foram aparecendo como '% 20 anos na resultando Salvar nome do arquivo de diálogo. Acabei de substituir os espaços com sublinhados, e que trabalhou.
Este não é de nomes a melhor solução, mas ela não funciona. Isso também significa que você tem que ter o nome do arquivo disponível para torná-lo parte da URI original, que bagunça poder, com o fluxo de trabalho do seu programa. Se ele está sendo gerado ou recuperado a partir de um banco de dados durante a chamada do lado do servidor que gera o PDF, pode ser necessário para mover o código que gera o nome do arquivo de javascript, como parte de um envio de formulário ou se se trata de um banco de dados torná-lo um chamada ajax rápida de obter o nome do arquivo ao construir o URL que resulta no PDF inline.
Se você está tomando o nome do arquivo a partir de uma entrada do usuário em um formulário, em seguida, que deve ser validado não contêm caracteres de escape, que vai incomodar os usuários.
Espero que ajude.
Tente colocar o nome do arquivo no final do URL, antes de quaisquer outros parâmetros. Isso funcionou para mim. http://www.setasign.de/support/ tips-and-tricks / filename-in-browser-plugin /
Em ASP.NET 2.0 alterar o URL de
http://www. server.com/DocServe.aspx?DocId=XXXXXXX
para
http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX
Isso funciona para o Acrobat 8 ??e o nome do arquivo SaveAs padrão agora é MySaveAsFileName.pdf
.
No entanto, você tem que restringir os caracteres permitidos em MySaveAsFileName
(sem períodos, etc.).
mod_rewrite
do Apache pode resolver isso.
Eu tenho um serviço web com um ponto final na /foo/getDoc.service
. Claro Acrobat irá salvar arquivos como getDoc.pdf
. Eu adicionei as seguintes linhas em apache.conf
:
LoadModule RewriteModule modules/mod_rewrite.so
RewriteEngine on
RewriteRule ^/foo/getDoc/(.*)$ /foo/getDoc.service [P,NE]
Agora, quando eu solicitar /foo/getDoc/filename.pdf?bar&qux
, ele é reescrito internamente para /foo/getDoc.service?bar&qux
, então eu estou batendo o ponto de extremidade correto do serviço web, mas Acrobat acha que vai salvar meu arquivo como filename.pdf
.
Se você usar asp.net, você pode controlar pdf filename através nome do arquivo página (url). Como outros usuários escreveu, Acrobat é um pouco s ... quando se escolher o nome do arquivo pdf quando você pressionar botão "Salvar": leva o nome da página, remove a extensão e adicionar ".pdf". Então /foo/bar/GetMyPdf.aspx dá GetMyPdf.pdf.
A única solução que eu encontrei é o de gerir "dinâmicos" nomes de página através de um manipulador de asp.net:
- criar uma classe que implementa IHttpHandler
- mapear um manipulador no web.config limitada à classe
Mapping1: todas as páginas têm uma raiz comum (MyDocument _):
<httpHandlers>
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Mapping2: nome do arquivo completamente livre (precisa de uma pasta no caminho):
<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Algumas dicas aqui (o pdf é criado dinamicamente usando iTextSharp):
http: // fhtino. blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html
Em vez de anexo que você pode tentar em linha:
Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");
I usado em linha em uma aplicação web anterior que gerou saída Crystal Reports em PDF e enviados que no navegador para o usuário.
diálogo de download de arquivo (PDF) com Salvar e opção aberta ??p>
Pontos para lembrar:
- Voltar Stream com o tamanho da matriz correta do serviço
- Leia o arrary byte do fluxo com comprimento de byte correta com base no comprimento do fluxo.
- set contenttype correta ??li>
Aqui está o código para o fluxo de leitura e abrir o diálogo de download de arquivo para arquivo 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();
}
}
Eu acredito que isto já foi mencionado em um sabor ou de outra, mas vou tentar e estado em minhas próprias palavras.
Ao contrário do que isto:
/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true
Eu uso este:
/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1
Ao invés de ter processo de "exportar" o pedido, quando uma solicitação é recebida, eu olho no URL para GeneratePDF = 1. Se encontrado, eu corro qualquer código que foi executado em "exportar" em vez de permitir o meu sistema para tentar procurar e servir a um PDF no /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf
localização. Se GeneratePDF não é encontrado na URL, eu simplesmente transmitir o arquivo solicitado. (Note que eu não posso simplesmente redirecionar para o arquivo solicitado - ou então eu ia acabar em um loop infinito)
Você pode sempre ter dois links. Um que abre o documento dentro do navegador, e outro para baixá-lo (usando um tipo de conteúdo incorreto). Isto é o que o Gmail faz.
Para quem ainda olhando para isso, usei a solução encontrada aqui e funcionou maravilhosamente. Graças Fabrizio!
A maneira que eu resolvi esse (com PHP) é a seguinte:
Suponha que a sua URL é SomeScript.php?id=ID&data=DATA
e o arquivo que você deseja usar é TEST.pdf
.
Alterar o URL para SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf
.
É importante que o último parâmetro é o nome do arquivo que você quer Adobe para usar (o 'EXT' pode ser sobre qualquer coisa). Certifique-se não há caracteres especiais na string acima, BTW.
Agora, no topo da SomeScript.php
, adicione:
$_REQUEST = MakeFriendlyURI( $_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']);
Em seguida, adicione esta função para SomeScript.php
(ou sua biblioteca de função):
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
Agora $_REQUEST
(ou $_GET
se você preferir) é acessado como $_REQUEST['id']
normal, $_REQUEST['data']
, etc.
E Adobe irá utilizar o seu nome do arquivo desejado como padrão salvar como ou info-mail quando você envia-lo em linha.
Eu estava redirecionado aqui porque eu tenho o mesmo problema. Eu também tentei solução de Troy Howard mas é não parece trabalho.
A abordagem que eu fiz em um presente é para não mais objeto de resposta uso para gravar o arquivo na mosca. Desde o PDF já está existente no servidor, o que eu fiz foi para redirecionar minha página apontando para o arquivo PDF. Funciona muito bem.
http://forums.asp.net/t/143631.aspx
Espero que minha explicação vaga deu-lhe uma idéia.
Créditos para Vivek .
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;
}
Verifique com
curl -I https://example.com/file.pdf
O Firefox 62.0b5 (64-bit): Ok.
Chrome 67.0.3396.99 (64-Bit): Ok.
IE. 11: Nenhum comentário
Tente isso, se o seu executável é "get.cgi"
http: //server,org/get.cgi/filename .pdf arquivo? = filename.pdf
Sim, é completamente insano. Não há nenhum arquivo chamado "filename.pdf" no servidor, não é o diretório em tudo sob o get.cgi executável.
Mas parece trabalho. O servidor ignora o filename.pdf eo leitor pdf ignora o "get.cgi"
Dan