web-dev-qa-db-fra.com

Décompression des fichiers

Je souhaite afficher les fichiers OpenOffice , .odt et .odp à l'aide d'un navigateur Web.

Ces fichiers sont des fichiers zippés. En utilisant Ajax, je peux obtenir ces fichiers du serveur mais ce sont des fichiers compressés. Je dois les décompresser en utilisant JavaScript , j'ai essayé d'utiliser inflate.js, http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt , mais sans succès.

Comment puis-je faire ceci?

69
user69260

J'ai écrit un dézipper en Javascript. Ça marche.

Il repose sur lecteur de fichier binaire de Andy G.P. Na et certains RFC1951 gonflent la logique de notmasteryet . J'ai ajouté la classe ZipFile.

exemple de travail:
http://cheeso.members.winisp.net/Unzip-Example.htm (lien mort)

La source:
http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip (lien mort)

[~ # ~] nb [~ # ~] : les liens sont morts; Je vais bientôt trouver un nouvel hôte.

La source comprend une page de démonstration ZipFile.htm et 3 scripts distincts, un pour la classe zipfile, un pour la classe inflate et un pour une classe de lecteur de fichier binaire. La démo dépend également de jQuery et de jQuery UI. Si vous venez de télécharger le fichier js-Zip.zip, toutes les sources nécessaires sont là.


Voici à quoi ressemble le code de l'application en Javascript:

// In my demo, this gets attached to a click event.
// it instantiates a ZipFile, and provides a callback that is
// invoked when the Zip is read.  This can take a few seconds on a
// large Zip file, so it's asynchronous. 
var readFile = function(){
    $("#status").html("<br/>");
    var url= $("#urlToLoad").val();
    var doneReading = function(Zip){
        extractEntries(Zip);
    };

    var zipFile = new ZipFile(url, doneReading);
};


// this function extracts the entries from an instantiated Zip
function extractEntries(Zip){
    $('#report').accordion('destroy');

    // clear
    $("#report").html('');

    var extractCb = function(id) {
        // this callback is invoked with the entry name, and entry text
        // in my demo, the text is just injected into an accordion panel.
        return (function(entryName, entryText){
            var content = entryText.replace(new RegExp( "\\n", "g" ), "<br/>");
            $("#"+id).html(content);
            $("#status").append("extract cb, entry(" + entryName + ")  id(" + id + ")<br/>");
            $('#report').accordion('destroy');
            $('#report').accordion({collapsible:true, active:false});
        });
    }

    // for each entry in the Zip, extract it. 
    for (var i=0; i<Zip.entries.length;  i++) {
        var entry = Zip.entries[i];

        var entryInfo = "<h4><a>" + entry.name + "</a></h4>\n<div>";

        // contrive an id for the entry, make it unique
        var randomId = "id-"+ Math.floor((Math.random() * 1000000000));

        entryInfo += "<span class='inputDiv'><h4>Content:</h4><span id='" + randomId +
            "'></span></span></div>\n";

        // insert the info for one entry as the last child within the report div
        $("#report").append(entryInfo);

        // extract asynchronously
        entry.extract(extractCb(randomId));
    }
}

La démo fonctionne en plusieurs étapes: Le readFilefn est déclenché par un clic et instancie un objet ZipFile, qui lit le fichier Zip. Il existe un rappel asynchrone pour la fin de la lecture (généralement en moins d'une seconde pour les zips de taille raisonnable). Dans cette démonstration, le rappel est maintenu dans la variable locale doneReading, qui appelle simplement extractEntries, ce qui décompresse aveuglément tout le contenu du fichier Zip fourni. Dans une application réelle, vous choisiriez probablement certaines des entrées à extraire (permettre à l'utilisateur de sélectionner ou de choisir une ou plusieurs entrées par programme, etc.).

extractEntries fn itère sur toutes les entrées et appelle extract() sur chacune d'elles, en passant un rappel. La décompression d'une entrée prend du temps, peut-être 1 ou plus pour chaque entrée du fichier zip, ce qui signifie que l'asynchronisme est approprié. Le rappel d'extraction ajoute simplement le contenu extrait à un accordéon jQuery sur la page. Si le contenu est binaire, alors il est formaté comme tel (non montré).


Cela fonctionne, mais je pense que l'utilitaire est quelque peu limité.

Pour une chose: c'est très lent. Il faut environ 4 secondes pour décompresser le fichier AppNote.txt 140k de PKWare. La même décompression peut être effectuée en moins de 0,5 dans un programme .NET.  [~ # ~] edit [~ # ~] : Le fichier ZipFile en Javascript se décompresse considérablement plus rapidement que cela à présent, dans IE9 et dans Chrome. Il est toujours plus lent qu'un programme compilé, mais il est très rapide pour une utilisation normale du navigateur.

Pour un autre: il ne fait pas de streaming. Fondamentalement, il insère dans la mémoire tout le contenu du fichier zip. Dans un environnement de programmation "réel", vous ne pouvez lire que les métadonnées d'un fichier Zip (64 octets par entrée, par exemple), puis lire et décompresser les autres données à votre guise. Il n'y a aucun moyen de faire IO comme cela en javascript, pour autant que je sache, par conséquent, la seule option est de lire l'intégralité du fichier Zip dans la mémoire et d'y effectuer un accès aléatoire. Cela signifie demandes déraisonnables en mémoire système pour les fichiers Zip volumineux, ce qui n'est pas vraiment un problème pour un fichier Zip plus petit.

En outre: il ne gère pas le fichier Zip "de cas général" - il existe de nombreuses options Zip que je n'ai pas pris la peine d'implémenter dans la décompression - comme le cryptage Zip, le cryptage WinZip, Zip64 Noms de fichiers encodés en UTF-8, etc. ( [~ # ~] éditer [~ # ~] - il gère maintenant les noms de fichiers encodés en UTF-8). La classe ZipFile gère les bases, cependant. Certaines de ces choses ne seraient pas difficiles à mettre en œuvre. J'ai ne classe de chiffrement AES en Javascript; qui pourrait être intégré pour prendre en charge le cryptage. La prise en charge de Zip64 serait probablement inutile pour la plupart des utilisateurs de Javascript, car elle est conçue pour prendre en charge des fichiers zip> 4 Go - il n'est pas nécessaire de les extraire dans un navigateur.

Je n'ai pas non plus testé le cas de décompression du contenu binaire. En ce moment, il décompresse le texte. Si vous avez un fichier binaire compressé, vous devez éditer la classe ZipFile pour le gérer correctement. Je n'ai pas trouvé comment faire ça proprement. Il fait maintenant des fichiers binaires.


[~ # ~] modifier [~ # ~] - J'ai mis à jour la bibliothèque et la démo de décompression JS. Il fait maintenant des fichiers binaires, en plus du texte. Je l'ai rendu plus résistant et plus général - vous pouvez maintenant spécifier le codage à utiliser lors de la lecture de fichiers texte. La démo est également développée - elle montre, entre autres, la décompression d'un fichier XLSX dans le navigateur.

Donc, même si je pense que son utilité et son intérêt sont limités, cela fonctionne. Je suppose que cela fonctionnerait dans Node.js.

61
Cheeso

J'utilise Zip.js et cela semble être très utile. Ça vaut le coup d'oeil!

Vérifiez le démo Décompressez , par exemple.

24
Dani bISHOP

J'ai trouvé jszip très utile. Je ne l’ai utilisé jusqu’à présent que pour la lecture, mais ils ont également des fonctionnalités de création/édition.

Code sage, il ressemble à quelque chose comme ça

var new_Zip = new JSZip();
new_Zip.load(file);
new_Zip.files["doc.xml"].asText() // this give you the text in the file

Une chose que j’ai remarquée est qu’il semble que le fichier doit être au format de flux binaire (lu en utilisant le fichier .readAsArrayBuffer de FileReader (), sinon je recevais des erreurs disant que je pourrais avoir un fichier Zip corrompu.

11
AlvaroFG

Exemple de code est donné sur le site de l'auteur . Vous pouvez utiliser babelfish pour traduire les textes (japonais en anglais).

D'après ce que je comprends en japonais, ce code de décompression Zip est conçu pour décoder les données Zip (flux) et non les archives Zip.

2
OcuS

J'ai écrit un cours pour ça aussi. http://blog.another-d-mention.ro/programming/read-load-files-from-Zip-in-javascript/ Vous pouvez charger des ressources de base telles que javascript/css/images directement à partir du Zip en utilisant des méthodes de classe. J'espère que ça aide

2
TheBrain

Si vous devez également prendre en charge d’autres formats ou si vous avez besoin de bonnes performances, vous pouvez utiliser ceci bibliothèque WebAssembly

c'est promis, il utilise WebWorkers pour le filetage et l'API est en fait un module ES simple

2
MySqlError

J'ai écrit "Binary Tools for JavaScript", un projet open source qui offre la possibilité de décompresser, unrar et untar: https://github.com/codedread/bitjs

Utilisé dans mon lecteur de bande dessinée: https://github.com/codedread/kthoom (également en source ouverte).

HTH!

2
codedread