Télécharger le fichier d'URL de données

127

Je joue avec l'idée de créer un utilitaire zip / décompression entièrement basé sur JavaScript auquel tout le monde peut accéder à partir d'un navigateur. Ils peuvent simplement faire glisser leur zip directement dans le navigateur et cela leur permettra de télécharger tous les fichiers qu'il contient. Ils peuvent également créer de nouveaux fichiers zip en faisant glisser des fichiers individuels dans.

Je sais que ce serait mieux de le faire côté serveur, mais ce projet est juste pour un peu de plaisir.

Faire glisser des fichiers dans le navigateur devrait être assez facile si je profite des différentes méthodes disponibles. (Style Gmail)

L'encodage / décodage devrait, espérons-le, bien se passer. J'ai vu des bibliothèques zip as3, donc je suis sûr que cela devrait me convenir.

Mon problème est de télécharger les fichiers à la fin.

window.location = 'data:jpg/image;base64,/9j/4AAQSkZJR....' 

cela fonctionne bien dans Firefox mais pas dans Chrome.

Je peux parfaitement intégrer les fichiers sous forme d'images dans Chrome <img src="data:jpg/image;ba.." />, mais les fichiers ne seront pas nécessairement des images. Ils peuvent être de n'importe quel format.

Quelqu'un peut-il penser à une autre solution ou à une sorte de solution de contournement?

Mikee
la source
Le support actuel est malheureusement plutôt limité
Casebash

Réponses:

42

Idées:

  • Essayez un <a href="data:...." target="_blank">(non testé)

  • Utilisez downloadify au lieu des URL de données (cela fonctionnera également pour IE)

Pekka
la source
@jcubic merci d'avoir signalé le lien mort. Le nouvel emplacement de téléchargement semble être github.com/dcneiner/Downloadify
Pekka
Si vous ne pouvez pas utiliser Flash mais exécutez un composant Java côté serveur, vous pouvez utiliser ceci: github.com/suprememoocow/databounce . Il utilise un servlet pour «rebondir» les données du client. Il serait assez facile d'effectuer la même astuce dans d'autres technologies côté serveur, telles que Python, ASP.NET, etc.
Andrew Newdigate
Existe-t-il un moyen de le faire sans flash? URL de données pour tous les navigateurs sauf IE et une sorte de foo ActiveX pour IE? (De cette façon, j'ai réussi à lire de la musique sans flash: audio HTML5 pour tous les navigateurs mais IE et ActiveX pour IE.)
panzi
Downloadify attend un lecteur flash dans le navigateur. Si l'utilisateur n'a pas de lecteur flash, le fichier ne sera pas téléchargé
Jeevanandan J
187

Si vous souhaitez également donner un nom suggéré au fichier (au lieu du `` téléchargement '' par défaut), vous pouvez utiliser ce qui suit dans Chrome, Firefox et certaines versions d'IE:

function downloadURI(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  delete link;
}

Et l'exemple suivant montre son utilisation:

downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");
owencm
la source
6
Vous pouvez simplifier cela avec link.click()au lieu de votre eventFire-fonction ... jsfiddle.net/ARTsinn/Ezx5m
yckart
3
Belle solution. mais que devient le lien après?
webshaker
6
La variable 'link' sort du champ d'application à la fin de la fonction (notez que nous ne l'avons jamais ajoutée au dom), elle sera donc récupérée peu de temps après.
owencm
8
Cela ne fonctionne que dans Chrome. Si vous voulez que cela fonctionne dans Firefox / IE, regardez la réponse de @MartinoDino.
TrueWill
1
J'ai essayé avec download.js , comme suggéré ici et cela semble fonctionner. :)
joaorodr84
56

function download(dataurl, filename) {
  var a = document.createElement("a");
  a.href = dataurl;
  a.setAttribute("download", filename);
  a.click();
}

download("data:text/html,HelloWorld!", "helloWorld.txt");

ou:

function download(url, filename) {
fetch(url).then(function(t) {
    return t.blob().then((b)=>{
        var a = document.createElement("a");
        a.href = URL.createObjectURL(b);
        a.setAttribute("download", filename);
        a.click();
    }
    );
});
}

download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");

Zibri
la source
événement de clic sur un élément inexistant: D pas besoin d'appendchild.
Zibri
1
Oui. vous pouvez simplement appeler a.click () après avoir créé l'élément 'a', puis définir le href de a.
user1709076
dans le passé, appeler a.click () directement ne fonctionnait pas mais cela fonctionnait avec l'événement. Maintenant, ils fonctionnent tous les deux.
Zibri
1
Cela fonctionne dans la plupart des navigateurs modernes, mais je note que l'ajout au document puis la suppression est nécessaire pour prendre en charge certains navigateurs plus anciens.
owencm
3
Votre deuxième solution doit être utilisée chaque fois que le dataUri devient trop gros (dépend du navigateur, mais Chrome n'accepte pas les Uri de plusieurs mégaoctets selon mon expérience). Voir également stackoverflow.com/questions/38781968/… .
neural5torm
27

Je veux partager mon expérience et aider quelqu'un bloqué sur les téléchargements qui ne fonctionnent pas dans Firefox et la réponse mise à jour à 2014. L'extrait ci-dessous fonctionnera à la fois dans Firefox et Chrome et il acceptera un nom de fichier:

  // Construct the <a> element
  var link = document.createElement("a");
  link.download = thefilename;
  // Construct the uri
  var uri = 'data:text/csv;charset=utf-8;base64,' + someb64data
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  // Cleanup the DOM
  document.body.removeChild(link);
Martino Dino
la source
4
Malheureusement, cela ne fonctionne pas dans Safari. Safari ne semble pas reconnaître l' downloadattribut. Merci de toute façon, c'est aussi proche que possible pour le moment.
Moritz Petersen
ceci provoque la redirection de la fenêtre vers la valeur href pour moi dans IE 11. prevetDefault (); n'arrête pas le comportement dans IE
b_dubb
1
Merci, aussi si btoan'est pas défini (par exemple dans le projet frontend node eslinted) const btxt = new Buffer(text).toString('base64'); const uri = 'data:text/csv;charset=utf-8;base64,' + btxt + ';'
Ivan Borshchov
2
la suppression du lien est inutile, elle sort de la portée sur la ligne suivante et sera garbage collection, ce n'est pas une cible valide pour la suppression.
macdja38
1
pas besoin de document.body.appendChild ... voir ma réponse stackoverflow.com/a/45905238/236062
Zibri
13

Voici une solution JavaScript pure que j'ai testée fonctionnant sous Firefox et Chrome mais pas dans Internet Explorer:

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
    link.href = dataUrl;
    document.body.appendChild(link);
    link.click();

    // Cleanup the DOM
    document.body.removeChild(link);
    delete link;
}

Solutions multi-navigateurs trouvées jusqu'à présent:

downloadify -> Nécessite Flash

databounce -> Testé dans IE 10 et 11, et ne fonctionne pas pour moi. Nécessite un servlet et une certaine personnalisation. (Détecte incorrectement le navigateur. J'ai dû mettre IE en mode de compatibilité pour tester, jeu de caractères par défaut dans le servlet, objet d'options JavaScript avec chemin de servlet correct pour les chemins absolus ...) Pour les navigateurs non-IE, il ouvre le fichier dans la même fenêtre.

download.js -> http://danml.com/download.html Une autre bibliothèque similaire mais non testée. Prétend être du JavaScript pur, ne nécessitant ni servlet ni Flash, mais ne fonctionne pas sur IE <= 9.

Jésus MC
la source
download.js est plutôt bon. Je viens de faire une vérification rapide sur IE11, cela fonctionne. Merci beaucoup!
Ricky Jiao
12

Il existe plusieurs solutions mais elles dépendent de HTML5 et n'ont pas encore été complètement implémentées dans certains navigateurs. Les exemples ci-dessous ont été testés dans Chrome et Firefox (fonctionne en partie).

  1. Exemple de canevas avec prise en charge de l'enregistrement dans un fichier. Définissez simplement votre document.location.hrefURI de données.
  2. Exemple de téléchargement d'ancre . Il utilise <a href="your-data-uri" download="filename.txt">pour spécifier le nom du fichier.
Viacheslav Dobromyslov
la source
3
exemple de toile mène à 404
Karel Bílek
L'attribut de téléchargement fonctionne pour moi, pour une URL de données pdf dans Chrome et Mobile Safari.
bbsimonbb
7

Combinant les réponses de @owencm et @ Chazt3n, cette fonction permettra de télécharger du texte depuis IE11, Firefox et Chrome. (Désolé, je n'ai pas accès à Safari ou Opera, mais veuillez ajouter un commentaire si vous essayez et que cela fonctionne.)

initiate_user_download = function(file_name, mime_type, text) {
    // Anything but IE works here
    if (undefined === window.navigator.msSaveOrOpenBlob) {
        var e = document.createElement('a');
        var href = 'data:' + mime_type + ';charset=utf-8,' + encodeURIComponent(text);
        e.setAttribute('href', href);
        e.setAttribute('download', file_name);
        document.body.appendChild(e);
        e.click();
        document.body.removeChild(e);
    }
    // IE-specific code
    else {
        var charCodeArr = new Array(text.length);
        for (var i = 0; i < text.length; ++i) {
            var charCode = text.charCodeAt(i);
            charCodeArr[i] = charCode;
        }
        var blob = new Blob([new Uint8Array(charCodeArr)], {type: mime_type});
        window.navigator.msSaveOrOpenBlob(blob, file_name);
    }
}

// Example:
initiate_user_download('data.csv', 'text/csv', 'Sample,Data,Here\n1,2,3\n');
kevinarpe
la source
1

Pour toute personne ayant des problèmes dans IE:

Veuillez valider la réponse ici par Yetti: enregistrer la toile localement dans IE

dataURItoBlob = function(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

var blob = dataURItoBlob(uri);
window.navigator.msSaveOrOpenBlob(blob, "my-image.png");
Chazt3n
la source
0

Votre problème se résume essentiellement à "tous les navigateurs ne le prendront pas en charge".

Vous pouvez essayer une solution de contournement et diffuser les fichiers décompressés à partir d'un objet Flash, mais vous perdriez alors la pureté JS uniquement (de toute façon, je ne sais pas si vous pouvez actuellement «faire glisser des fichiers dans le navigateur» sans une sorte de solution de contournement Flash - est-ce une fonctionnalité HTML5 peut-être?)

Piskvor a quitté le bâtiment
la source