(HTML) Baixe um arquivo PDF em vez de abri-lo no navegador quando clicado

115

Eu queria saber como fazer um link de arquivo PDF para download em vez de abri-los no navegador. Como isso é feito em html? (Eu presumo que seja feito via javascript ou algo assim).

404Error
fonte
3
Que eu saiba, isso não é um comportamento programável. A maioria dos navegadores terá suas próprias configurações para o comportamento do que fazer com tipos de arquivo específicos no download.
Bart
1
A partir do HTML5, o OP deve atualizar a resposta correta para a resposta de Sarim.
Omar Tariq de
possível duplicata de Force to open "Save As ..." popup aberto no link de texto clique para pdf em HTML
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Esta pergunta também foi respondida aqui: stackoverflow.com/a/30714824/847235
intrepidis

Respostas:

38

Você não pode fazer isso com HTML. É uma solução baseada em servidor. Você deve transmitir o arquivo para que o navegador acione a caixa de diálogo Salvar.

Eu aconselho não fazer isso. A forma como um usuário interage com um PDF deve ser deixada para o usuário.

ATUALIZAÇÃO (2014):

Então ... essa resposta ainda recebe muitos votos negativos. Presumo que parte disso seja que isso foi respondido há 4 anos e, como Sarim aponta, agora existe o atributo HTML 5download que pode lidar com isso.

Eu concordo e acho que a resposta de Sarim é boa (provavelmente deve ser a resposta escolhida se o OP algum dia retornar). No entanto, essa resposta ainda é a maneira confiável de lidar com isso (como a resposta de Yiğit Yener aponta e - estranhamente - as pessoas concordam). Embora o atributo de download tenha ganhado suporte, ainda é irregular:

http://caniuse.com/#feat=download

DA.
fonte
18
Eu sei que tem um ano - mas eu discordo. Existem circunstâncias em que forçar esse comportamento é muito importante para o fluxo do aplicativo. A resposta real é definir a disposição do conteúdo no cabeçalho como "anexo" em vez de "embutido".
user158017
9
Eu concordo que em outras circunstâncias, deixar isso para o controle do usuário é melhor. No entanto, cheguei a este tópico em busca de uma resposta, e a "resposta" marcada não era uma resposta - era "você não deveria fazer isso". Para mim, isso não é uma resposta para a pergunta. Em vez disso, dê uma resposta específica e também aconselhar.
user158017
1
Às vezes, a pergunta está errada. ;) De qualquer forma, em relação ao seu problema, isso é tudo um problema de UX. Forçar a web a se comportar de maneiras específicas às vezes é necessário, mas geralmente há soluções melhores de uma perspectiva de UX. Além disso, minha resposta está correta. Você não pode fazer o que deseja com HTML (que é o que a pergunta estava pedindo). É uma solução do lado do servidor.
DA.
1
Esta é uma das minhas respostas mais estranhas já postadas. As pessoas ainda encontram seu caminho aqui para votar contra ele. O que é ótimo! Mas seria interessante saber por quê.
DA.
3
Sobre essa votação negativa, pode ser a queda da civilização o quão fácil é parecer involuntariamente arrogante no texto. Essa resposta me impressiona tanto pela opinião condescendente quanto pela falta de respostas. Em vez do parágrafo 1, basta adicionar a httptag à pergunta. Em vez do parágrafo 2: "Você pode querer reconsiderar se impedir a visualização imediata de PDF é do interesse de todos os usuários. Dito isso ..." Então, suponha que o OP e os futuros leitores sejam adultos e prossiga para uma resposta acionável, como Yener .
Bob Stein,
133

Com html5, agora é possível. Defina um elemento de atributo "download".

<a href="http://link/to/file" download="FileName">Download it!</a>

Fonte: http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download

Sarim
fonte
É melhor você ir com esta solução, se houver suporte. Esta é uma maneira de verificar se éif ("download" in document.createElement("a")){ ... }
pmrotule
Eu adicionei outra resposta abaixo (hack ruim embora), embora esta ainda seja a forma preferida, talvez a forma de hack possa ser oferecida para navegadores sem suporte.
Sarim
Existe uma maneira de especificar o texto para o pdf em vez de mencionar o caminho do arquivo? Preciso criar pdf a partir de um html div, mas não desejo abrir outra janela, o download deve ser semelhante a esta resposta.
T.Adak
1
Como agora em agosto de 2019, o suporte do navegador parece ter sido aprimorado para esse recurso, consulte: w3schools.com/tags/att_a_download.asp
Daniel Resch
2
Observe que o atributo de download só é compatível com solicitações da mesma origem.
Quentin
82

Isso só é possível com a configuração de um cabeçalho de resposta http pelo código do lado do servidor. Nomeadamente;

Content-Disposition: attachment; filename=fname.ext
Yiğit Yener
fonte
2
esta é a resposta perfeita - apenas encontre a maneira de fazer isso na linguagem apropriada do lado do servidor.
user158017
Exemplo do Apache . Exemplo de frasco .
Bob Stein,
Infelizmente, o iOS ainda irá visualizar e não baixar arquivos PDF, mesmo se a disposição do conteúdo for 'anexo'.
Jorn van de Beek
14

Você precisa alterar os cabeçalhos http enviados. Dependendo do seu servidor, você pode modificar seu .htaccess da seguinte maneira:

<FilesMatch "\.(?i:pdf)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>
cara php
fonte
Não há necessidade de mentir sobre o tipo de conteúdo. Definir a disposição do conteúdo é suficiente.
Quentin
9

você precisará usar um script PHP (ou outra linguagem do lado do servidor para isso)

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>

e use o httacces para redirecionar (reescrever) para o arquivo PHP em vez do pdf

código barba
fonte
Hmm, funciona muito bem quando abro o arquivo php diretamente. Mas quando tento usar o redirecionamento, como aqui: Redirect 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.phpe tento abrir o arquivo pdf, ele ainda abre o original no navegador, em vez de baixar a versão renomeada ...
ellockie
ATUALIZAÇÃO: Funciona quando não há nenhum arquivo sendo chamado diretamente (como "Catalogue.pdf" no meu exemplo). Então, o redirecionamento funciona perfeitamente. Obrigado!
ellockie
8

Você pode usar

Response.AddHeader("Content-disposition", "attachment; filename=" + Name);

Veja este exemplo:

http://www.codeproject.com/KB/aspnet/textfile.aspx

Isso vale para ASP.NET. Tenho certeza de que você pode encontrar soluções semelhantes em todas as outras linguagens do servidor. No entanto, até onde sei, não existe uma solução em javascript.

mihsathe
fonte
esta é a resposta (assim como aquela relacionada para PHP). o ponto é que o cabeçalho da resposta http deve ser editado.
user158017
5

Sem o atributo html5, pode-se fazer isso usando php:

Crie um arquivo php chamado download.php com este código:

<?php
ob_start();
$file = "yourPDF.pdf"

if (file_exists($file)) 
{
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit();
}

Agora, se você deseja iniciar automaticamente o download do pdf, escreva este javascript:

<script>window.location = "download.php";</script>

Se você quiser que isso funcione em um link, use isso ...

<a href='javascript:window.location = "download.php"'>
    Download it!
</a>
hlozancic
fonte
4
Apenas um aviso de que você precisa ter cuidado ao fazer isso com parâmetros de URL. Por exemplo $file = $_GET['$file'];. Porque também se pode chamar download.php?file=../../../wp-config.phpou qualquer outro recurso fornecido. A verificação adicional de extensões, tipos MIME e caminhos permitidos para download (e remoção de coisas como "../") são muito importantes!
Giel Berkers
sou eu ou fazer <a href='javascript...'> é exatamente o mesmo que colocar diretamente o link em<a href='download.php'> ?
allan.simon
5

Quando você deseja baixar diretamente qualquer imagem ou arquivo pdf do navegador, em vez de abri-lo em uma nova guia e, em seguida, em javascript, você deve definir o valor para o atributo de download de criar link dinâmico

    var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    var event = document.createEvent('Event');
    event.initEvent('click', true, true); 
    save.dispatchEvent(event);
   (window.URL || window.webkitURL).revokeObjectURL(save.href);

Para uma nova atualização do Chrome, algum evento de tempo não está funcionando. para o seguinte código será usado

  var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    document.body.appendChild(save);
    save.click();
    document.body.removeChild(save);

Anexar filho e remover filho é útil para o Firefox, navegador Internet explorer apenas. No Chrome, ele funcionará sem adicionar e remover filho

Prasad Joshi
fonte
2

A solução que funcionou melhor para mim foi aquela escrita por Nick em seu blog

A ideia básica de sua solução é usar o mod de cabeçalho dos servidores Apache e editar o .htaccess para incluir uma diretiva FileMatch que força todos os arquivos * .pdf a agirem como um fluxo em vez de um anexo. Embora isso não envolva a edição de HTML (de acordo com a pergunta original), não requer nenhuma programação em si.

A primeira razão pela qual eu preferi a abordagem de Nick é porque ela me permitiu defini-la em uma base por pasta, de forma que PDFs em uma pasta ainda pudessem ser abertos no navegador enquanto permitia outras (aquelas que gostaríamos que os usuários editassem e depois carregassem novamente) a ser forçado como downloads.

Também gostaria de acrescentar que existe uma opção com PDFs para postar / enviar formulários preenchíveis por meio de uma API para seus servidores, mas isso leva algum tempo para implementar.

A segunda razão é porque o tempo é uma consideração. Escrever um manipulador de arquivo PHP para forçar a disposição do conteúdo no cabeçalho () também levará menos tempo do que uma API, mas ainda mais do que a abordagem de Nick.

Se você sabe como ligar um mod do Apache e editar o .htaccss, pode fazer isso em cerca de 10 minutos. Requer hospedagem Linux (não Windows). Essa pode não ser a abordagem apropriada para todos os usos, pois requer acesso ao servidor de alto nível para configurar. Portanto, se você disse acesso é provavelmente porque já sabe fazer essas duas coisas. Se não, verifique o blog de Nick para obter mais instruções.

Strixy
fonte
2

Como a forma html5 (minha resposta anterior) não está disponível em todos os navegadores, aqui está outra forma um pouco hack.

Esta solução requer que você esteja servindo o arquivo pretendido do mesmo domínio OU tenha permissão CORS.

  1. Primeiro baixe o conteúdo do arquivo via XMLHttpRequest (Ajax).
  2. Em seguida, crie um URI de dados codificando o conteúdo do arquivo em base64 e defina o tipo de mídia como application/octet-stream. O resultado deve ser semelhante a

data:application/octet-stream;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

Agora pronto location.href = data. Isso fará com que o navegador baixe o arquivo. Infelizmente, você não pode definir o nome ou a extensão do arquivo dessa forma. Mexer com o tipo de mídia pode render alguma coisa.

Veja os detalhes: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs

Sarim
fonte
1

Se você estiver usando HTML5 (e acho que hoje em dia todo mundo usa isso), existe um atributo chamado download.

ex. <a href="somepathto.pdf" download="filename">

aqui filenameé opcional, mas se fornecido, levará este nome para o arquivo baixado.

Akshay
fonte
Infelizmente, tenho que admitir que sou muito estúpido para entender essa tag. Eu coloquei isto: <a href="download/Curriculum_it.pdf.zip">Download curriculum</a>ou aquilo: <a href="download/Curriculum_it.pdf.zip" download="Curriculum_it">Download curriculum</a>e não consigo ver absolutamente nenhuma diferença em como funciona. Ambos baixando meu .zip. E no segundo, usar a opção de nome de arquivo parece não fazer nada.
Garavani
0

O comportamento deve depender de como o navegador está configurado para lidar com vários tipos de MIME. Nesse caso, o tipo MIME é application / pdf. Se você deseja forçar o navegador a baixar o arquivo, pode tentar forçar um tipo MIME diferente nos arquivos PDF. Eu não recomendo isso, pois deve ser a escolha do usuário o que acontecerá quando eles abrirem um arquivo PDF.

Aleksi Yrttiaho
fonte
0

Você pode usar download.js ( https://github.com/rndme/download e http://danml.com/download.html ). Se o arquivo estiver em um URL externo, você deve fazer uma solicitação Ajax, mas se não estiver, você pode usar a função:

download(Path, name, mime)

Leia a documentação para obter mais detalhes no GitHub.

Vishnu S.
fonte
Esta é a melhor solução de javascript para downloads em outro domínio.
Edhowler
-1

Finalmente descobri ...... criar uma tag âncora dinâmica e clicar nela

<script> 
   $('#myclick').click(function(){
       $('body').append('<a id="link" href="mypdf.pdf" 
        download="Payment.pdf">&nbsp;</a>');
       $('#link')[0].click();
   });
</script>

'Payment.pdf' é apenas para nome personalizado.

Pushpender Singh
fonte
Não há necessidade de gerar o link dinamicamente.
Quentin
Observe que o atributo de download só é compatível com solicitações da mesma origem.
Quentin
Esta parece ser a mesma resposta como este a partir de três anos antes.
Quentin