8741 sujets

Développement web côté serveur, CMS

Pages :
Bonsoir à tous
J'ai essayé d'utiliser les fonctions ZIP en php avec comme résultat un fichier .zip que mon PC sous Windows 10 ne parvient pas à ouvrir.
Avez vous déjà utilisé ces fonctions ? Quelles sont les précautions à prendre ?
Modifié par PapyJP (30 May 2024 - 15:15)
Modérateur
Bonjour,

peut tu préciser la version de PHP que tu utilises et partager ton script de base qui ne fonctionne pas ? Est tu certains que ton fichier crée contient quelque chose?

Je n'ai pas eu de soucis de mon coté les quelques fois que j'en ai fait usage pour créer des archives, le seul soucis que j'ai eu c'est avec le mime-type retourné sous windows qui diffère si tu cherches à tester le type du fichier.
Je teste maintenant ces mime-type : application/zip , x-zip-compressed et application/gzip (archives zip et tar.gz) Mais cela n'a aucune incidence sur la création du fichier lui même.

cdt
Salut

C'est normalement "relativement" simple de ziper en php. Pourrais tu partagé le code ? peut être que ton code ne "close" pas le fichier et que tu du coup il est toujours utilisé par ton programme ou autre. Mais difficile de savoir.
Merci de vos réponses

Mon problème est très simple : je veux zipper UN SEUL fichier.

Voici le code php :

function zipFile($path) {
		$zipPath = "$path.zip"; 
		if(file_exists($zipPath)) {
			$zipdate = filemtime($zipPath);
			if($zipdate < filemtime($path)) unlink($zipPath);
			else return $zipPath;
		}
		$archive = new ZipArchive();
		$archive -> open($zipPath, ZipArchive::CREATE);
		$archive -> addFile($path);
		$archive -> close();
		return $zipPath;
	}

Dans cette fonction je passe en argument le fichier à zipper et je récupère le fichier .zip
En apparence le programme se déroule sans problème mais quand j'ouvre le fichier .zip il est vide.
Mon environnement : https://www.alma-musica.net/phpinfo.php
Modifié par PapyJP (30 May 2024 - 10:33)
Ok peut être rajouter une gestion des erreurs pour mieux comprendre

function zipFile($path) {
    $zipPath = "$path.zip"; 
    if(file_exists($zipPath)) {
        $zipdate = filemtime($zipPath);
        if($zipdate < filemtime($path)) unlink($zipPath);
        else return $zipPath;
    }
    
    $archive = new ZipArchive();
    if ($archive->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
        die("Impossible d'ouvrir ou de créer le fichier ZIP");
    }
    
    if (!$archive->addFile($path, basename($path))) {
        $archive->close();
        die("Impossible d'ajouter le fichier au ZIP");
    }
    
    $archive->close();
    
    return $zipPath;
}
J’ai affiché le résultat de addFile, ça affiche "true".
Donc le problème est ailleurs.
Modérateur
PapyJP a écrit :
J’ai affiché le résultat de addFile, ça affiche "true".
Donc le problème est ailleurs.

Surement Smiley smile ,
car ton script en l'état fonctionne sans bug sous windows.

Tu peut aussi le réécrire comme ceci pour mettre à jour l'archive au besoin
		function zipFile($path) {
		$zipPath = "$path.zip"; 
		if(file_exists($zipPath)) {
			$zipdate = filemtime($zipPath);
		}
		else  {
			$zipdate=0;
			touch($zipPath);
		}
		if($zipdate < filemtime($path) ) {
			$archive = new ZipArchive();
			$archive -> open($zipPath, ZipArchive::OVERWRITE);// on efface le contenu de l'archive avant de la remettre à jour
			$archive -> addFile($path);
			$archive -> close();
			return $zipPath;
		}
		else {
			$zipdate = floor( (time() - $zipdate)/3600);
			echo "derniere mise à jour il y a {$zipdate} jours<br> <a href='{$zipPath}'>".basename($zipPath)."</a>";
		}
	}


Selon ce que tu souhaite faire avec ton return, ici le script propose le lien de téléchargement de l'archive déjà existante si le fichier à inclure n'a pas été mis à jour.

Tester les erreurs au cour du script est une bonne pratique pour le débogage. Cela permet aussi au visiteur de savoir qu'il y a eu un problème et en lui donnant un moyen de contact, cela diminue sa frustration. Certains messages d'erreur peuvent être utile à traiter pour le visiteur. https://www.php.net/manual/en/ziparchive.open.php donne une liste d'erreurs possible

Cdt
Modifié par gcyrillus (31 May 2024 - 09:26)
Merci de ta réponse
Effectivement un bon moyen de trouver une solution n’est pas tant de trouver l’erreur que réécrire la fonction autrement.
Bien entendu j’ai tout un mécanisme de trace et de gestion d’erreur que j’ai retiré de cet exemple pour en faciliter la lecture.
Modifié par PapyJP (31 May 2024 - 10:00)
Hélas ça ne marche pas mieux.

Le fichier zip de test est bien créé, mais quand j'essaie de l'ouvrir il est vide.
Le fichier à zipper fait 3.8Mo, le fichier zippé fait 0.5Mo, ce qui serait tout de même un zippage très efficace. Smiley cligne

Sauf illumination, je vais laisser tomber, ce qui veut dire zipper lez fichier un à un et les transférer sur le site par ftp. Smiley decu
Merci pour cette réponse
Pour autant que je comprenne, ce post explique comment est sensé fonctionner la librairie que je tente d’utiliser.
Dans un premier temps je pensais que c’était moi qui ne l’utilisais pas bien, mais tout semble indiquer que c’est plus vicieux que ça, et il faudrait avoir un support technique à la hauteur chez mon hébergeur, ce qui n’est pas le cas (mais apparemment pas pire que l’autre hébergeur que j’utilise pour un autre site)
Modérateur
PapyJP a écrit :
Hélas ça ne marche pas mieux.

Le fichier zip de test est bien créé, mais quand j'essaie de l'ouvrir il est vide.
Le fichier à zipper fait 3.8Mo, le fichier zippé fait 0.5Mo, ce qui serait tout de même un zippage très efficace. Smiley cligne

Sauf illumination, je vais laisser tomber, ce qui veut dire zipper lez fichier un à un et les transférer sur le site par ftp. Smiley decu


Est ce que tu as le même problème avec un fichier de petite taille ?
Si non, il s'agit peut-être d'un problème de ressources(memoire) ou de temps d’exécution (max_execution_time).
(Par exemple, j'ai un plugin pour un CMS qui transfère les articles du site dans un epub, un epub est un fichier zip , sur un hébergeur gratuit qui s'annonce sans limite, il ne fonctionne pas par manque de ressources: lenteur du serveur principalement et cette fois il ne s'agit pas d'un hébergement Free Smiley smile .)

Si ce que tu veut faire est en local, alors tu peut aussi tenter d'utiliser : https://www.php.net/manual/fr/function.exec.php en lançant en ligne de commande ton programme de compression windows ou un fichier batch (plus facile à tester) par exemple
exec('MonFichier.bat');

Note que cette fonction est souvent désactivée pour des raisons de sécurité.

Cordialement
Modifié par gcyrillus (31 May 2024 - 13:46)
Bonjour,
Le problème ne viendrait pas 'simplement' du nom de fichier $path, ou de son accessibilité au niveau du script ?
Cordialement
Hello,

Comment est-ce que tu essaies d'ouvrir ton fichier zip généré ?

Il est peut-être tout à fait valide mais le logiciel que tu utilises pour l'ouvrir ne supporte peut-être pas l'algorithme de compression utilisé par PHP.

Personnellement j'utilise 7zip, il est capable d'ouvrir un bien plus grand nombre de type d'archives que juste l'explorateur windows.

Est-ce que la taille du fichier généré est stable sur plusieurs exécutions ?
Si non, alors effectivement, il y a peut-être une question de ressources limitées ou de temps de traitement trop long.
Mais si oui, alors ce n'est probablement pas ça le problème.

Une taille de 0.5 Mo pour un fichier original de 3.8 Mo, ça ne me choque pas trop. Ca fait une compression à 87%, c'est tout à fait possible selon le type de fichier. Par exemple le texte et le code se compressent habituellement très bien.
Tiens d'ailleurs, c'est quoi comme type de fichier que tu tentes de compresser ?
PapyJP a écrit :
Merci pour cette réponse
Pour autant que je comprenne, ce post explique comment est sensé fonctionner la librairie que je tente d’utiliser.
Dans un premier temps je pensais que c’était moi qui ne l’utilisais pas bien, mais tout semble indiquer que c’est plus vicieux que ça, et il faudrait avoir un support technique à la hauteur chez mon hébergeur, ce qui n’est pas le cas (mais apparemment pas pire que l’autre hébergeur que j’utilise pour un autre site)


C'est dur, je propose juste Zlib ou 7zip.so. Désolé. Smiley hum
Bonjour à tous
J'ai enfin pu écluser les choses urgentes et je reviens à cette discussion.
Pour clarifier ce que je fais :
1) nous partons d'une partition musicale, par exemple
https://www.alma-musica.net/html/partitions/tests/AuClairDeLaLune.pdf
2) grâce à des outils appropriés et pas mal d'huile de coude nous produisons un "fichier d'apprentissage" permettant aux choristes de travailler leur partition
https://www.alma-musica.net/html/partitions/tests/AuClairDeLaLune.myrweb.html
je n'ai mis que la première ligne de la partition pour avoir un fichier moins gros.
3) en utilisant 7-zip nous en faisons des fichiers zip, que les gens peuvent charger sur leur PC
https://www.alma-musica.net/html/partitions/tests/AuClairDeLaLune.myrweb.html.zip
vous remarquerez qu'il n'est pas beaucoup compressé, car l'essentiel du fichier d'origine consiste en des données numériques qui sont décodées par un script qui est appelé au chargement du fichier .myrweb.html
4) nous mettons le tout sur notre site à la disposition de choristes.

Ce que j'aurais aimé faire, c'est éviter la phase 3 en zippant le fichier sur le serveur.
Dans une deuxième étape, j'aurais remplacé dans le fichier l'appel à un script extérieur par le contenu de ce script, ce qui aurait permis de travailler totalement sans connexion, car je n'ai pas trop envie de le faire sur le PC à la mimine, ce qui aurait été une source d'erreurs.
Par ailleurs les producteurs du script le modifient plusieurs fois par an, il aurait été facile de refaire les fichiers .zip par programme.
Modifié par PapyJP (07 Jun 2024 - 15:40)
Modérateur
Bonjour PapyJP,

En utilisant ton fichier exemple et en testant avec php 7.2.19 et 8.3.4 (je n'ai pas ta version ) et le script suivant :
<?php
	error_reporting(E_ALL);
	function zipFile($path) {
		if(file_exists($path)) {
			$zipPath = "$path.zip"; 
			if(file_exists($zipPath)) {
				$zipdate = filemtime($zipPath);
			}
			else  {
				$zipdate=0;
				touch($zipPath);
			}
			if($zipdate < filemtime($path) ) {
				$archive = new ZipArchive();
				$archive -> open($zipPath, ZipArchive::OVERWRITE);
				$archive -> addFile($path);
				$archive -> close();
				//return $zipPath;
				// ou renvoi direct en telechargement via header() ??
				header('Content-disposition: attachment; filename='.basename($zipPath));
				header('Content-type: application/zip');
				readfile($zipPath);
			}
			else {
				$zipdate = floor( (time() - $zipdate)/3600/24);
				echo "<p>Derniere mise à jour du fichier <b>{$path}</b> il y a <b>{$zipdate}</b> jours.<br>
				Lien de téléchargement: <a href='{$zipPath}'>".basename($zipPath)."</a>.</p>";
			}
		}
		else {
			echo "<p style='text-align:center'>Le fichier <b>$path</b> n'existe pas encore ou est mal orthographié.</p>";
		}
	}
	zipFile('AuClairDeLaLune.myrweb.html');
?>


l'archive est bien généré et est ouvrable et dezipable sous windows.
Est ce aussi le cas pour toi sur ce petit fichier ?
Pour répondre aux questions implicitement contenues dans ton exemple, le but n'est pas de télécharger des fichiers zip produits à la volée.
L'administrateur du site (moi en l'occurrence) télécharge les fichiers .myrweb.html et lance ensuite un programme qui rafraîchit les fichiers .zip correspondant si nécessaire, d'où le test sur la date qui permet de savoir si le fichier .zip existe déjà et si oui s'il a été créé avant ou après la mise à jour du fichier .myrweb.html.

J'ai recopié le test en enlevant ce qui n'est pas utile à ce que je veux faire, ce qui donne :

<?php
	$root = $_SERVER['DOCUMENT_ROOT'];
	include_once "$root/html/common.php";
	error_reporting(E_ALL);

	function zipFile($path) {
		$path = fullPath($path);			// c'est à dire dans ce cas "$root/$path"
		if(file_exists($path)) {
			$zipPath = "$path.zip";
			if(file_exists($zipPath)) {
				$zipdate = filemtime($zipPath);
			}
			else  {
				$zipdate=0;
				touch($zipPath);
			}
			if($zipdate < filemtime($path) ) {
				$archive = new ZipArchive();
				$archive -> open($zipPath, ZipArchive::OVERWRITE);
				$archive -> addFile($path);
				$archive -> close();
			}
		}
		else {
			echo "<p style='text-align:center'>Le fichier <b>$path</b> n'existe pas encore ou est mal orthographié.</p>";
		}
	}
	zipFile('/html/partitions/tests/AuClairDeLaLune.myrweb.html');
?>


et j'ai eu comme résultat :

1- qu'il a bien créé un fichier .zip
upload/1717855221-48769-myrzip1.png

******************************************************************************
2 - si j'essaie d'ouvrir ce fichier en local sous Windows 10, j'obtiens
upload/1717855459-48769-myrzip2.png

******************************************************************************
3 - si j'insiste à utiliser la fonction décompression j'obtiens
upload/1717855606-48769-myrzip3.png

Voilà voiloù !
Une idée sur ce qui cloche ?
Modifié par PapyJP (08 Jun 2024 - 16:17)
Modérateur
PapyJP a écrit :
Pour répondre aux questions implicitement contenues dans ton exemple, le but n'est pas de télécharger des fichiers zip produits à la volée.
L'administrateur du site (moi en l'occurrence) télécharge les fichiers .myrweb.html et lance ensuite un programme qui rafraîchit les fichiers .zip correspondant si nécessaire, d'où le test sur la date qui permet de savoir si le fichier .zip existe déjà et si oui s'il a été créé avant ou après la mise à jour du fichier .myrweb.html.

J'ai recopié le test en enlevant ce qui n'est pas utile à ce que je veux faire, ce qui donne :

&lt;?php
	$root = $_SERVER['DOCUMENT_ROOT'];
	include_once "$root/html/common.php";
	error_reporting(E_ALL);

	function zipFile($path) {
		$path = fullPath($path);			// c'est à dire dans ce cas "$root/$path"
		if(file_exists($path)) {
			$zipPath = "$path.zip";
			if(file_exists($zipPath)) {
				$zipdate = filemtime($zipPath);
			}
			else  {
				$zipdate=0;
				touch($zipPath);
			}
			if($zipdate &lt; filemtime($path) ) {
				$archive = new ZipArchive();
				$archive -&gt; open($zipPath, ZipArchive::OVERWRITE);
				$archive -&gt; addFile($path);
				$archive -&gt; close();
			}
		}
		else {
			echo "&lt;p style='text-align:center'&gt;Le fichier &lt;b&gt;$path&lt;/b&gt; n'existe pas encore ou est mal orthographié.&lt;/p&gt;";
		}
	}
	zipFile('/html/partitions/tests/AuClairDeLaLune.myrweb.html');
?&gt;


et j'ai eu comme résultat :

1- qu'il a bien créé un fichier .zip
upload/1717855221-48769-myrzip1.png

******************************************************************************
2 - si j'essaie d'ouvrir ce fichier en local sous Windows 10, j'obtiens
upload/1717855459-48769-myrzip2.png

******************************************************************************
3 - si j'insiste à utiliser la fonction décompression j'obtiens
upload/1717855606-48769-myrzip3.png

Voilà voiloù !
Une idée sur ce qui cloche ?


Pas vraiment, la taille du fichier semble correspondre à ce que j'obtiens et mon Windows 10 à jour ne me fait pas de misère, c'est un mystère pour moi.

A tout hasard, ton fichier html est bien encode en utf-8 ?
Cdt
Regarde le contenu du fichier https://www.alma-musica.net/html/partitions/tests/AuClairDeLaLune.myrweb.html
<html>
<head>
<!-- Mise à jour 26/05/2024 14:52:59 -->
<meta charset="UTF-8">
<script src="https://www.myriad-users.com/cgi-bin/js.pl?myrweb"/></script>
<!-- le code de l'application en JavaScript minifié -->
<title>AU CLAIR DE LA LUNE</title>
<style type="text/css">
html, body {width:100%;height:80%;}
body {font-family:sans-serif;text-align:center;}
h1 {font-size:20px;font-family: serif;}
div.myrweb {width:80%;min-width:700px;margin:auto;height:80%;}
h1 button {
position: relative;
height:1.8em;
width:1.8em;
border:none;
vertical-align: middle;
border:2px solid #0172cc;
color:#0172cc;
border-radius:50%;
text-align:center;
text-decoration:none;
font-size:0.8em;
padding:2px;
margin-left:1em;
margin-top:-0.25em;
cursor:pointer;
}
h1 button::after {content:"?"}
.reduced > * {display:none;}
.reduced .myrweb {display:block;}
</style>
<script>function reduce(){
document.body.classList.toggle('reduced');
var myrweb = document.querySelector('div.myrweb');
myrweb.addEventListener('click', function(event){event.stopPropagation();
document.body.classList.add('reduced')});
}</script>
</head>
<body onclick="reduce()">
<h1>
<script>document.write(document.title)</script>
<button onclick="window.open('https://www.alma-musica.net/html/partitions/myrweb/myrweb.html')"> </button>
</h1>
<div class="myrweb" data-myrweb="" data-id="a6643571">

<script>var data_a6643571_varb64=".....";</script> 
<!-- toutes les données graphiques, sonores, ... des centaines de Ko -->

</div>
</body>
</html>

Remarque : il n'est pas licite d'indenter le code, mais ça reste lisible.
Modifié par PapyJP (09 Jun 2024 - 10:26)