Passé sous le radar, ce nouvel attribut est particulièrement utile pour les fichiers PDF par exemple, ouvert par défaut par un plugiciel ou Acrobat. L’attribut « download » permet de spécifier que la cible sera téléchargée, au lieu d’être ouverte, après avoir cliqué sur l’hyperlien. La valeur de l’attribut sera le nom du fichier à télécharger, sans aucune restriction. Le navigateur détecte automatiquement l’extension du fichier (.img, .pdf, .txt, .html, etc.) et l’ajoute au nom du fichier. ATTENTION : Ça ne fonctionne pas toujours avec mon Firefox, il faut absolument spécifier l’extension, enfin pas toujours. Si j’ouvre pour la première fois le téléchargement dans Photoshop, l’extension n’est pas reconnue. Si je l’ouvre par l’outil de Windows, ça fonctionne. Et une fois fait, il fonctionne ensuite avec Photoshop! Un bon conseil, spécifier toujours l’extension...
Si aucun nom n’est spécifier, le nom original sera utilisé, dans l’exemple suivant « t_tut3.gif »
<a href="/img/t_tut3.gif" download>Logo des Trucsweb</a>
Si l’attribut est spécifié, le fichier télécharger aura son nom, dans l’exemple suivant « logo_trucsweb.gif ».
// Exemple SANS extension
<a href="/img/t_tut3.gif" download="Logo Trucsweb">Logo des Trucsweb</a>
// Exemple AVEC extension
<a href="/img/t_tut3.gif" download="Logo Trucsweb.gif">Logo des Trucsweb</a>
Compatible Chrome, Edge (13), Firefox et Opera, l’attribut n’est pas encore compatible IE (il ne le sera jamais) et Safari(!). Mais quand même, quand on sait combien complexe était l’opération, c’est déjà ça! Et surtout, au pire les usager de Safari pourront toujours faire un clic droit et forcer manuellement le téléchargement. quand à IE... Noter qu’avec Google Chrome, vous pouvez glisser l’hyperlien directement sur le bureau!
Test JavaScript
Pour tester si le navigateur est compatible. Noter que je n’ai aucune idée à quoi ça peut servir. L’alternative est le langage serveur, mais le JavaScript est exécuté seulement après la réponse du serveur. Si votre navigateur ne supporte pas cet attribut, il faudrait rechercher la page! Bon, c’est toujours pratique à des fins de développement...
<script>
var a=document.createElement('a');
if(typeof a.download !="undefined") {
// Supporte l'attribut « download »
} else {
// NE supporte PAS l'attribut « download »
}
<script>
Et un exemple jQuery, qui fait le contraire. Il ajoute l’attribut s’il est compatible. Encore une fois, ça ne change rien au fond. Mais dans ce cas-ci, on change le texte pour aviser l’internaute que le lien sera téléchargé...
<script> $( document ).ready(function() { var oDiv = $('#oMonLienTelechargement'); oDiv.append($('<a>').attr('href', 'document.pdf').attr('download', 'mondocument.pdf').text('Télécharger mon document PDF')); if (!('download' in oDiv.children('a:first').get(0))) { oDiv.append(' (Sauver le fichier "document.pdf")'); } }); <script> <div id="oMonLienTelechargement"></div>
Plusieurs exemples du même genre disponibles dans le tutoriel « Using the HTML5 Download Attribute » par Rob Gravelle. Dont qui ajoute l’attribut à une image et un JavaScript qui crée à la volé un lien <a> aux images.
Download dynamique
En fait ce n’est pas un bon titre, c’est plutôt une région contenteditable
qu’on va télécharger à l’aide de la méthode window.URL.createObjectURL()
. Voir l’exemple A demo of the HTML5 download attribute.
Côté serveur
Historiquement, il fallait forcer le bon entête HTTP « application/force-download » ou « application/pdf » ou « application/zip » etc. Et la seule manière était avec un langage serveur. Ici l’exemple que j’utilise en ASP pour télécharger un PDF dans un dossier static, bonne pratique pour éviter de se faire pirater.
<%@ CodePage=65001 Language="VBScript"%> <% if request.querystring("id") <> "" then dim strFileName, varBuffer strFileName = request.querystring("id") & ".pdf" response.write Server.MapPath("\") & "\documents\pdf\"&strFileName Set ObjStr = Server.CreateObject("ADODB.Stream") ObjStr.Type = 1 ’AdBinary - Binário ObjStr.Open ObjStr.LoadFromFile Server.MapPath("\") & "\documents\pdf\"&strFileName varBuffer = ObjStr.Read Response.buffer = true Response.AddHeader "content-disposition","attachment;" Response.ContentType = "application/pdf" ’Response.ContentType = "application/force-download" Response.CacheControl = "public" Response.BinaryWrite varBuffer end if %>
Exemple PHP très complet (Source : PHP Force Download - Keep Track of What’s Going Down par David Walsh).
// grab the requested file's name
$file_name = $_GET['file'];
// make sure it's a file before doing anything!
if(is_file($file_name)) {
/*
Do any processing you'd like here:
1. Increment a counter
2. Do something with the DB
3. Check user permissions
4. Anything you want!
*/
// required for IE
if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }
// get the file mime type using the file extension
switch(strtolower(substr(strrchr($file_name, '.'), 1))) {
case 'pdf': $mime = 'application/pdf'; break;
case 'zip': $mime = 'application/zip'; break;
case 'jpeg':
case 'jpg': $mime = 'image/jpg'; break;
default: $mime = 'application/force-download';
}
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($file_name)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($file_name)); // provide file size
header('Connection: close');
readfile($file_name); // push it out
exit();
}
Références
- Using the HTML5 Download Attribute » par Rob Gravelle
- A demo of the HTML5 download attribute
- PHP Force Download - Keep Track of What’s Going Down par David Walsh