Como fazer download de arquivos PDF no link HTML?
Pergunta
Estou dando ligação de um arquivo pdf na minha página web para download, como abaixo
<a href="myfile.pdf">Download Brochure</a>
O problema é quando o usuário clica neste link, em seguida
- Se o usuário tiver instalado o Adobe Acrobat, em seguida, ele abre o arquivo na mesma janela do navegador no Adobe Reader.
- Se o Adobe Acrobat não estiver instalado, em seguida, pop-up para o usuário para download do arquivo.
Mas eu quero sempre pop-up para o usuário para download, independentemente do "Adobe acrobat" está instalado ou não.
Por favor me diga como posso fazer isso?
Solução
Em vez de ligar para o arquivo .PDF, em vez fazer algo como
<a href="pdf_server.php?file=pdffilename">Download my eBook</a>
que gera um cabeçalho personalizado, abre o PDF (seguro binário) e imprime os dados para o navegador do usuário, então eles podem optar por salvar o PDF apesar de suas configurações do navegador. O pdf_server.php deve ficar assim:
header("Content-Type: application/octet-stream");
$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
PS: e, obviamente, executar algumas checagens na variável "arquivo" para impedir as pessoas de roubar seus arquivos tais como não aceitam extensões de arquivo, negar barras, adicione .pdf ao valor
Outras dicas
Este é um problema comum, mas poucas pessoas sabem que há uma solução simples HTML 5:
<a href="./directory/yourfile.pdf" download="newfilename">Download the pdf</a>
Onde newfilename
é o nome sugerido para o usuário salvar o arquivo. Ou será o padrão para o nome do arquivo na serverside se você deixá-lo vazio, como este:
<a href="./directory/yourfile.pdf" download>Download the pdf</a>
Compatibilidade: Eu testei isso no Firefox 21 e ferro, tanto funcionou bem. Pode não funcionar em navegadores HTML5-incompatíveis ou desatualizados. O único navegador que eu testei que não forçou transferência é IE ...
Verifique a compatibilidade aqui: http://caniuse.com/#feat=download
através de cada linha do arquivo NÃO loop. Use readfile em vez disso, a sua mais rápido. Este é fora do site php: http://php.net/manual/en/function.readfile.php
$file = $_GET["file"];
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=' . urlencode(basename($file)));
// header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
Certifique-se de higienizar a variável get como alguém poderia baixar alguns arquivos php ...
Em vez de usar um script PHP, ler e limpar o arquivo, é mais puro para reescrever o cabeçalho usando .htaccess
. Isto irá manter uma URL "bom" (myfile.pdf
vez de download.php?myfile
).
<FilesMatch "\.pdf$">
ForceType applicaton/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
Eu encontrei uma maneira de fazê-lo com HTML velho liso e JavaScript / jQuery que degrada graciosamente. Testado em IE7-10, Safari, Chrome e FF:
HTML para o link de download:
<p>Thanks for downloading! If your download doesn't start shortly,
<a id="downloadLink" href="...yourpdf.pdf" target="_blank"
type="application/octet-stream" download="yourpdf.pdf">click here</a>.</p>
jQuery (código JavaScript puro seria mais detalhado) que simula clicando no link depois de um pequeno atraso:
var delay = 3000;
window.setTimeout(function(){$('#downloadLink')[0].click();},delay);
Para tornar isso mais robusta você pode adicionar detecção de recurso HTML5 e se ele não está lá, em seguida, usar window.open()
para abrir uma nova janela com o arquivo.
Esta é a chave:
header("Content-Type: application/octet-stream");
Tipo de conteúdo application / x-pdf-documento ou application / pdf é enviado ao enviar arquivo PDF. Adobe Reader geralmente define o manipulador para este tipo MIME de modo navegador vai passar o documento para Adobe Reader quando qualquer um dos tipos PDF MIME é recebido.
Há uma maneira mais fácil em HTML5: Adicionar um atributo Download
.
É apoiado pela maioria dos navegadores modernos.
<a download href="file.pdf">Download PDF</a>
Eu sei que eu sou muito tarde para responder a isso, mas eu encontrei um hack para fazer isso em javascript.
function downloadFile(src){
var link=document.createElement('a');
document.body.appendChild(link);
link.href= src;
link.download = '';
link.click();
}
Tente isto:
<a href="pdf_server_with_path.php?file=pdffilename&path=http://myurl.com/mypath/">Download my eBook</a>
O código dentro pdf_server_with_path.php é:
header("Content-Type: application/octet-stream");
$file = $_GET["file"] .".pdf";
$path = $_GET["path"];
$fullfile = $path.$file;
header("Content-Disposition: attachment; filename=" . Urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . Filesize($fullfile));
flush(); // this doesn't really matter.
$fp = fopen($fullfile, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
Aqui está uma abordagem diferente. Eu prefiro, em vez de contar com o suporte ao navegador, ou o endereço deste na camada de aplicação, a lógica uso do servidor web.
Se você estiver usando Apache, e pode colocar um arquivo .htaccess no diretório relevante você poderia usar o código abaixo. Claro, você poderia colocar isso em httpd.conf, assim, se você tem acesso a isso.
<FilesMatch "\.(?i:pdf)$">
Header set Content-Disposition attachment
</FilesMatch>
A directiva FilesMatch é apenas um regex para que pudesse ser definido como granular como você quer, ou você pode adicionar em outras extensões.
A linha de cabeçalho faz a mesma coisa como a primeira linha nos scripts PHP acima. Se você precisa definir as linhas Content-Type, bem, você poderia fazê-lo da mesma maneira, mas eu não achei que necessário.
Eu resolvi meus que usam toda a url do arquivo PDF (em vez de apenas colocar o nome do arquivo ou local para href): a href = "domínio. com / pdf / filename.pdf"
Se você precisa taxa de download limite, usar este código !!
<?php
$local_file = 'file.zip';
$download_file = 'name.zip';
// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5;
if(file_exists($local_file) && is_file($local_file))
{
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($local_file));
header('Content-Disposition: filename='.$download_file);
flush();
$file = fopen($local_file, "r");
while(!feof($file))
{
// send the current file part to the browser
print fread($file, round($download_rate * 1024));
// flush the content to the browser
flush();
// sleep one second
sleep(1);
}
fclose($file);}
else {
die('Error: The file '.$local_file.' does not exist!');
}
?>
Para mais informações clique aqui
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>File Uploader</title>
<script src="../Script/angular1.3.8.js"></script>
<script src="../Script/angular-route.js"></script>
<script src="../UserScript/MyApp.js"></script>
<script src="../UserScript/FileUploder.js"></script>
<>
.percent {
position: absolute;
width: 300px;
height: 14px;
z-index: 1;
text-align: center;
font-size: 0.8em;
color: white;
}
.progress-bar {
width: 300px;
height: 14px;
border-radius: 10px;
border: 1px solid #CCC;
background-image: -webkit-gradient(linear, left top, left bottom, from(#6666cc), to(#4b4b95));
border-image: initial;
}
.uploaded {
padding: 0;
height: 14px;
border-radius: 10px;
background-image: -webkit-gradient(linear, left top, left bottom, from(#66cc00), to(#4b9500));
border-image: initial;
}
</>
</head>
<body ng-app="MyApp" ng-controller="FileUploder">
<div>
<table ="width:100%;border:solid;">
<tr>
<td>Select File</td>
<td>
<input type="file" ng-model-instant id="fileToUpload" onchange="angular.element(this).scope().setFiles(this)" />
</td>
</tr>
<tr>
<td>File Size</td>
<td>
<div ng-repeat="file in files.slice(0)">
<span ng-switch="file.size > 1024*1024">
<span ng-switch-when="true">{{file.size / 1024 / 1024 | number:2}} MB</span>
<span ng-switch-default>{{file.size / 1024 | number:2}} kB</span>
</span>
</div>
</td>
</tr>
<tr>
<td>
File Attach Status
</td>
<td>{{AttachStatus}}</td>
</tr>
<tr>
<td>
<input type="button" value="Upload" ng-click="fnUpload();" />
</td>
<td>
<input type="button" value="DownLoad" ng-click="fnDownLoad();" />
</td>
</tr>
</table>
</div>
</body>
</html>
Em um aplicativo Ruby on Rails (especialmente com algo como a gema do camarão e os Rails Prawnto plugin), você pode fazer isso um pouco mais simples do que um cheio no roteiro (como o exemplo PHP anterior).
Em seu controlador:
def index
respond_to do |format|
format.html # Your HTML view
format.pdf { render :layout => false }
end
end
O render: layout => false parte diz ao navegador para abrir o "Gostaria de baixar este arquivo?" solicitar em vez de tentar tornar o PDF. Então você seria capaz de fazer o link com o arquivo normalmente: http://mysite.com/myawesomepdf.pdf