J'ai écrit un unzipper en Javascript. Elle fonctionne.
Il s'appuie sur Andy G. P. Na fichier binaire de lecteur et certains RFC1951 gonfler la logique de notmasteryet. J'ai ajouté de la classe ZipFile.
exemple:
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 trouver un nouvel hôte bientôt.
Inclus dans le source est un ZipFile.htm page de démonstration, et les 3 scripts distincts, l'un pour la classe zipfile, l'un pour le gonfler de classe, et l'autre pour un fichier binaire classe de lecteur. La démo dépend aussi de jQuery et jQuery UI. Si vous venez de télécharger la js-zip.zip fichier, tous les de la source nécessaire est là.
Voici ce que le code de l'application ressemble 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émonstration fonctionne en deux étapes: L' readFile
fn est déclenché par un clic, et instancie un ZipFile objet, qui lit le fichier zip. Il y a un rappel asynchrone pour une fois la lecture terminée (qui se produit généralement en moins d'une seconde de taille raisonnable, des zips) - dans cette démonstration, le rappel est tenue dans la doneReading variable locale, qui appelle tout simplement extractEntries
, ce qui
seulement aveuglément dézippe tout le contenu du fichier zip. Dans une application réelle, vous devriez probablement choisir un certain nombre d'entrées à extraire (permettre à l'utilisateur de sélectionner, ou choisir une ou plusieurs entrées de la programmation, etc).
L' extractEntries
fn passe en revue toutes les entrées, et les appels extract()
sur chacun d'eux, le passage d'un rappel. Décompression d'une entrée prend du temps, peut-être 1 ou plus pour chaque entrée dans la zipfile, ce qui signifie que l'asynchronie est approprié. L'extrait de rappel ajoute simplement l'extrait du contenu d'un accordéon jQuery sur la page. Si le contenu est binaire, alors il est formaté en tant que tel (pas montré).
Il fonctionne, mais je pense que l'utilité est assez limitée.
Pour une chose: C'est très lent. Prend environ 4 secondes pour décompresser les 140k AppNote.txt fichier de PKWare. La même décompresser peut être fait en moins de .5 dans une .NET programme. EDIT: Le Javascript ZipFile déballe beaucoup plus rapide que ce maintenant, dans IE9 et Chrome. Il est encore plus lent qu'un programme compilé, mais il est beaucoup rapide pour le mode normal d'utilisation du navigateur.
Pour un autre: il ne fait pas de streaming. Essentiellement, il slurps dans la totalité du contenu de la zipfile dans la mémoire. Dans un "vrai" environnement de programmation vous avez pu lire dans que les métadonnées d'un fichier zip (par exemple, 64 octets par entrée), puis lire et décompresser les autres données comme vous le souhaitez. Il n'y a aucun moyen de le faire IO comme ça en javascript, autant que je sache, donc la seule option est de lire l'intégralité du zip dans la mémoire et ne random access en elle. Cela signifie qu'il va placer des exigences déraisonnables de la mémoire système pour les gros fichiers zip. Pas tellement un problème pour un petit fichier zip.
Aussi: Il ne gère pas le "cas général" fichier zip - il y a beaucoup de zip options que je n'ai pas pris la peine de mettre en œuvre dans le unzipper - ZIP cryptage, WinZip chiffrement, zip64, codé en UTF-8 les noms de fichiers, et ainsi de suite. (EDIT - il gère l'UTF-8 noms de fichiers). La classe ZipFile gère les bases, si. Certaines de ces choses ne serait pas difficile à mettre en œuvre. J'ai un cryptage AES de classe en Javascript, qui pourrait être intégrée à prendre en charge le chiffrement. Soutenir Zip64 serait probablement inutile pour la plupart des utilisateurs de Javascript, comme il est destiné à soutenir >4 go zipfiles - n'ont pas besoin d'extraire celles-ci dans un navigateur.
J'ai aussi n'a pas le test est le cas pour la décompression du contenu binaire. Pour l'instant il ouvre le texte. Si vous avez un fichier compressé (fichier binaire, vous auriez besoin de modifier la classe ZipFile de le gérer correctement. Je n'ai pas trouver comment le faire proprement. Il n'fichiers binaires maintenant, trop.
EDIT - j'ai mis à jour la JS décompresser de la bibliothèque et de démonstration. C'est maintenant les fichiers binaires, en plus du texte. Je l'ai fait, plus résiliente et plus générale - vous pouvez maintenant spécifier l'encodage à utiliser lors de la lecture de fichiers texte. Aussi la démo est élargi, il montre la décompression d'un fichier XLSX dans le navigateur, entre autres choses.
Ainsi, alors que je pense qu'il est de peu d'utilité et d'intérêt, il fonctionne. Je suppose que ce serait travailler dans Node.js.