Attention : Le contenu de ces pages n'a pas été mis à jour depuis longtemps. Il est probablement obsolète pour Firefox 4.0/Gecko 4.0 et supérieur. Pour du contenu plus récent, allez consulter developer.mozilla.org.

Lireextraire zip

Lire et extraire une archive zip

Mozilla est capable d'ouvrir, de lire et d'extraire des archives zip, mais il ne peut pas archiver lui-même. Voici un exemple montrant comment lister les fichiers présents dans une archive, lire leur contenu et les extraire dans un dossier.

Le code

 <?xml version="1.0" encoding="ISO-8859-1"?>
 <?xml-stylesheet href="[[chrome://global/skin/]]" type="text/css"?>
 <window
          title="Gestion des zip"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <script type='text/javascript'>
 <![CDATA[
 var zipFile = null;
 function lireZip(){
 var nsIFilePicker = Components.interfaces.nsIFilePicker;
 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
 fp.init(window, "Sélectionner une archive", nsIFilePicker.modeOpen);
 fp.appendFilter("Zip Files","*.zip");
 var res=fp.show();
 if (res==nsIFilePicker.returnOK)
 {
	zipFile = fp.file;
	var zip = Components.classes["@mozilla.org/libjar/zip-reader;1"].createInstance( Components.interfaces.nsIZipReader );
	zip.init(zipFile);
	zip.open();
	var it = zip.findEntries("*.txt");
	while (it.hasMoreElements())
	{
		var entry = it.getNext();
		entry = entry.QueryInterface(Components.interfaces.nsIZipEntry);
		pere = document.getElementById("zipFilesConteneur");
		fils = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label");
		fils.setAttribute("value",entry.name);
		pere.appendChild(fils);
		var contenu = zip.getInputStream(entry.name);
		var ouvert =   Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance( Components.interfaces.nsIScriptableInputStream );
		ouvert.init(contenu);
		lireContenu = ouvert.read (ouvert.available());
		alert(lireContenu);
	}
	zip.close();
	document.getElementById("extraire").disabled=false;
 }
 }
 function extraireZip(){
 	var nsIFilePicker = Components.interfaces.nsIFilePicker;
 	var fp =  Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
 	fp.init(window, "Sélectionner une destination", nsIFilePicker.modeGetFolder);
 	var res=fp.show();
 	if (res==nsIFilePicker.returnOK)
 	{
 		destFolder = fp.file;
 		chemin = destFolder.path;
 		var zip =  Components.classes["@mozilla.org/libjar/zip-reader;1"].createInstance(  Components.interfaces.nsIZipReader );
 		zip.init(zipFile);
 		zip.open();
 		var it = zip.findEntries("*"); //patern pour recuperer le contenu de notre zip
 		while (it.hasMoreElements())
 		{
			var entry = it.getNext();
			entry = entry.QueryInterface(Components.interfaces.nsIZipEntry);
			var destFolder = Components.classes["@mozilla.org/file/local;1"]
                     .createInstance(Components.interfaces.nsILocalFile);
			destFolder.initWithPath(chemin);
			entryChemin = entry.name.split('/');
			for(i in entryChemin){
				if(i==entryChemin.length-1 && entryChemin[i].length != 0){
					destFolder.append(entryChemin[i]);
					zip.extract ( entry.name , destFolder );
					break;
				}
				destFolder.append(entryChemin[i]);
				 try{destFolder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0664);}
				catch(e){}
			}
		}
		zip.close();
	}
 }
 ]]>
 </script>
 <vbox flex="1">
 <vbox flex="1" id="zipFilesConteneur">
 </vbox>
 <hbox>
 	<button flex="1" oncommand="lireZip()" label="lire zip"></button>
 	<button flex="1" oncommand="extraireZip()" id="extraire" label="extraire zip" disabled="true"></button>
 </hbox>
 </vbox>
 </window>

Explications

Lister et lire

On commence donc par l'ouverture d'une archive, que l'on sélectionne en utilisant un filemanager. On initialise le composant de manipulation zip avec le fichier ainsi obtenu, et on en récupère les entrées avec findEntries("*.txt") (la méthode attend un pattern comme argument, ce qui nous permet de ne récupérer que les fichiers qui nous intéressent, ici les fichiers .txt).

Pour lire le contenu des fichiers, nous le plaçons dans un flux avec la méthode getInputStream() que l'on peut ensuite manipuler avec le composant de lecture de flux.

Extraire

Pour extraire notre archive, on commence par sélectionner un dossier de destination. Puis on parcourt encore une fois les entrées de l'archive. La difficulté, ici, est de gérer l'arborescence. Si vous extrayez un fichier présent dans une arborescence, entry.name aura une forme de ce type "dossier/sousdossier/fichier". Il faut donc découper cette chaîne pour en extraire tous les dossiers et les créer un par un avec create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0664) (create() renvoyant une erreur si le dossier existe déjà, on le place dans un try catch). Ensuite seulement, on extrait le fichier.

Nota bene

Surtout ne pas oublier de réinitialiser le dossier de destination à chaque extraction de fichier. Pourquoi ? En effet à première vue, on n'en voit pas la nécessité, et j'ai mis un certain temps avant de comprendre où était l'erreur (car cela provoque une erreur, si si). En fait, destFolder.append(entry.name) ajoute entry.name à la fin du chemin de destFolder (on s'en rend compte en affichant, après coup, destFolder.path...). Du coup, au second passage, c'est comme si vous tentiez d'extraire un fichier dans un fichier ! Et ça, ça ne marche pas, mais alors pas du tout.

Lire et extraire une archive zip avec XULRunner 1.9

L'implémentation de nsIZipReader dans XULRunner 1.9 a légèrement changé et le code ci-dessus ne fonctionne plus. En effet, findEntries() ne retourne plus une nsISimpleEnumerator mais un nsIUTF8StringEnumerator, ce qui change quelques peu la donne pour les méthodes et fonctions employées durant l'extraction. hasMoreElements() est donc remplacé par hasMore(). On note aussi la "fusion" entre init() et open(). Enfin, on n'a plus besoin de QueryInterface puisqu'on a déjà une chaine de caractères. Voici donc une version compacté du code à utiliser avec XULRunner 1.9 :

 var zip =  Components.classes["@mozilla.org/libjar/zip-reader;1"].createInstance(  Components.interfaces.nsIZipReader );
 zip.open(zipFile);
 var it = zip.findEntries("*");
 while (it.hasMore())
        {
                var filename = it.getNext();
	        extracting_file.append(filename);
		zip.extract ( filename , extracting_file );
        }

C'est une version simplifiée et non récursive, mais il est facile d'adapter le code donné plus haut avec ces nouvelles méthodes.


Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.

Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.