web-dev-qa-db-fra.com

Est-il possible de spécifier un nom de fichier suggéré lors de l'utilisation de data: URI?

Si par exemple vous suivez le lien:

data:application/octet-stream;base64,SGVsbG8=

Le navigateur vous invite à télécharger un fichier contenant les données conservées en base64 dans le lien hypertexte lui-même. Est-il possible de suggérer un nom par défaut dans le balisage? Si non, existe-t-il une solution JavaScript?

214
MontyGomery

Utilisez l'attribut download:

<a download='FileName' href='your_url'>

Exemple en direct sur html5-demos.appspot.com/... .

Fonctionne actuellement sur Chrome, Firefox, Edge, Opera et Safari de bureau, mais pas iOS Safari ou IE11.

146
Dan Fabulich

Chrome rend cela très simple ces jours-ci:

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}
60
Holf

HTML uniquement: utilise l'attribut download:

<a download="logo.gif" href="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">Download transparent png</a>

Javascript seulement: vous pouvez sauvegarder n'importe quel URI de données avec ce code:

function saveAs(uri, filename) {
  var link = document.createElement('a');
  if (typeof link.download === 'string') {
    link.href = uri;
    link.download = filename;

    //Firefox requires the link to be in the body
    document.body.appendChild(link);
    
    //simulate click
    link.click();

    //remove the link when done
    document.body.removeChild(link);
  } else {
    window.open(uri);
  }
}

var file = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
saveAs(file, 'logo.gif');

Chrome, Firefox et Edge 13 + utiliseront le nom de fichier spécifié.

IE11, Edge 12 et Safari 9 (qui ne prend pas en charge l'attribut download) ) téléchargera le fichier avec leur nom par défaut ou ils l'afficheront simplement dans un nouvel onglet, s'il s'agit d'un type de fichier pris en charge: images, vidéos, fichiers audio,…


Si besoin d'une meilleure compatibilité maintenant , utilisez le basé sur Flash Downloadify comme un repli.

45
fregante

Selon RFC 2397 , non, il n'y en a pas.

Il ne semble pas non plus y avoir de attribut de l'élément <a> que vous puissiez utiliser.

Cependant, HTML5 a par la suite introduit l’attribut download sur l’élément <a>, bien qu’au moment de la rédaction, la prise en charge n’était pas universelle (pas de prise en charge MSIE, par exemple).

39
Alnitak

J'ai un peu cherché dans les sources firefox dans netwerk/protocol/data/nsDataHandler.cpp

le gestionnaire de données analyse uniquement le contenu/type et le jeu de caractères, et regarde s'il y a "; base64" dans la chaîne

le rfc spécifie pas de nom de fichier et au moins firefox ne gère aucun nom de fichier, le code génère un nom aléatoire plus ".part"

J'ai aussi vérifié le journal firefox

[b2e140]: DOCSHELL 6e5ae00 InternalLoad data:application/octet-stream;base64,SGVsbG8=
[b2e140]: Found extension '' (filename is '', handling attachment: 0)
[b2e140]: HelperAppService::DoContent: mime 'application/octet-stream', extension ''
[b2e140]: Getting mimeinfo from type 'application/octet-stream' ext ''
[b2e140]: Extension lookup on '' found: 0x0
[b2e140]: Ext. lookup for '' found 0x0
[b2e140]: OS gave back 0x43609a0 - found: 0
[b2e140]: Searched extras (by type), rv 0x80004005
[b2e140]: MIME Info Summary: Type 'application/octet-stream', Primary Ext ''
[b2e140]: Type/Ext lookup found 0x43609a0

fichiers intéressants si vous voulez regarder les sources de Mozilla:

data uri handler: netwerk/protocol/data/nsDataHandler.cpp
where mozilla decides the filename: uriloader/exthandler/nsExternalHelperAppService.cpp
InternalLoad string in the log: docshell/base/nsDocShell.cpp

Je pense que vous pouvez arrêter de chercher une solution pour l'instant, car je soupçonne qu'il n'y en a pas :)

comme noté dans ce fil, html5 a l'attribut download, il fonctionne aussi sur firefox 20 http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html# attr-hyperlink-download

21
sherpya

L'extrait de code Javascript suivant fonctionne dans Chrome en utilisant le nouvel attribut "download" des liens et en simulant un clic.

function downloadWithName(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  link.click();
}

Et l'exemple suivant montre son utilisation:

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")
14
owencm

Non.

Le but est que ce soit un flux de données, pas un fichier. La source de données ne doit pas savoir que l'agent utilisateur le traite comme un fichier ... et ce n'est pas le cas.

vous pouvez ajouter un attribut de téléchargement à l'élément d'ancrage.

échantillon:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>
8
cuixiping

En utilisant service workers , ceci est finalement possible dans le vrai sens du terme.

  1. Créez une fausse URL. Par exemple /saveAs/myPrettyName.jpg
  2. Utilisez l'URL dans <a href, <img src, window.open (url), absolument tout ce qui peut être fait avec une "vraie" URL.
  3. À l'intérieur du travailleur, capturez l'événement fetch et répondez avec les données correctes.

Le navigateur suggérera maintenant myPrettyName.jpg même si l'utilisateur ouvre le fichier dans un nouvel onglet et tente de le sauvegarder. Ce sera exactement comme si le fichier venait du serveur.

// In the service worker
self.addEventListener( 'fetch', function(e)
{
    if( e.request.url.startsWith( '/blobUri/' ) )
    {
        // Logic to select correct dataUri, and return it as a Response
        e.respondWith( dataURLAsRequest );
    }
});
5
Adria

Regardez ce lien: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html

Citation:

Cela fonctionne même (comme dans, ne pose pas de problème) avec; base64 à la fin
comme ceci (dans Opera au moins):

data: text/plain; charset = utf-8; en-têtes = Content-Disposition% 3A% 20attachment% 3B% 20filename% 3D% 22with% 20spaces.txt% 22% 0D% 0AContent-Language % 3A% 20en; base64,4oiaDQo% 3D

Il y a aussi quelques informations dans les messages restants de la discussion.

5
silex

Il existe un petit script de solution de contournement sur Google Code qui a fonctionné pour moi:

http://code.google.com/p/download-data-uri/

Il ajoute un formulaire avec les données qu'il contient, le soumet puis le supprime à nouveau. Hacky, mais ça a fait le travail pour moi. Nécessite jQuery.

Ce fil de discussion est apparu dans Google avant la page Code Google et j’ai pensé qu’il pourrait être utile d’avoir le lien ici aussi.

4
Fabian B.

Voici une version de jQuery basée sur la version de Holf et fonctionnant avec Chrome et Firefox alors que sa version semble ne fonctionner qu'avec Chrome. C'est un peu étrange d'ajouter quelque chose au corps pour faire cela, mais si quelqu'un a une meilleure option, je suis tout à fait d'accord.

var exportFileName = "export-" + filename;
$('<a></a>', {
    "download": exportFileName,
    "href": "data:," + JSON.stringify(exportData, null,5),
    "id": "exportDataID"
}).appendTo("body")[0].click().remove();
3
kgividen

C'est un peu ridicule, mais je me suis déjà retrouvé dans la même situation. J'étais en train de générer dynamiquement un fichier texte en javascript et je voulais le télécharger au téléchargement en l'encodant avec l'URI de données.

C'est possible avec mineurintervention majeure de l'utilisateur. Générer un lien <a href="data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>. Comme je l’ai dit, c’est inélégant, mais cela fonctionne si vous n’avez pas besoin d’une solution professionnelle.

Cela pourrait être rendu moins pénible en utilisant flash pour copier le nom dans le presse-papiers en premier. Bien sûr, si vous vous laissiez utiliser Flash ou Java (maintenant avec de moins en moins de navigateur pris en charge, je pense?), Vous pourriez probablement trouver un autre moyen de le faire.

3
ninjagecko

Celui-ci fonctionne avec Firefox 43.0 (ancien non testé):

dl.js:

function download() {
  var msg="Hello world!";
  var blob = new File([msg], "hello.bin", {"type": "application/octet-stream"});

  var a = document.createElement("a");
  a.href = URL.createObjectURL(blob);

  window.location.href=a;
}

dl.html

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8"/>
    <title>Test</title>
    <script type="text/javascript" src="dl.js"></script>
</head>

<body>
<button id="create" type="button" onclick="download();">Download</button>
</body>
</html>

Si le bouton est cliqué, un fichier nommé hello.bin est proposé au téléchargement. L'astuce consiste à utiliser Fichier au lieu de Blob .

référence: https://developer.mozilla.org/de/docs/Web/API/File

2
NeutronenStern
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var sessionId ='\n';
var token = '\n';
var caseId = CaseIDNumber + '\n';
var url = casewebUrl+'\n';
var uri = sessionId + token + caseId + url;//data in file
var fileName = "file.i4cvf";// any file name with any extension
if (isIE)
    {
            var fileData = ['\ufeff' + uri];
            var blobObject = new Blob(fileData);
            window.navigator.msSaveOrOpenBlob(blobObject, fileName);
    }
    else //chrome
    {
        window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
         window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) {
            fs.root.getFile(fileName, { create: true }, function (fileEntry) { 
                fileEntry.createWriter(function (fileWriter) {
                    var fileData = ['\ufeff' + uri];
                    var blob = new Blob(fileData);
                    fileWriter.addEventListener("writeend", function () {
                        var fileUrl = fileEntry.toURL();
                        var link = document.createElement('a');
                        link.href = fileUrl;
                        link.download = fileName;
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                    }, false);
                    fileWriter.write(blob);
                }, function () { });
            }, function () { });
         }, function () { });
    }
0
Sushama Pradhan