Problème export csv avec php

Bonjour,

  • j’ai un site qui tourne sur mon NAS DS918, sous wordpress / nginx / mariadb / PHP. Une des fonctionnalité est l’export de tableaux sql en csv via un script PHP. Pour cela, j’ai entre autre appliqué la méthode qui se trouve ici (https://gist.github.com/janschoepke/3e7a3639546d0d740c023e11289cf13d)
  • donc j’ai un code comme ceci : ($ress étant le résultat de ma requête sql)
			// creation du fichier csv à exporter
			// gestion du BOM (pour MS Excel) Byte Order Mark
			// compatibilité MS Excel Windows 
			$bom = chr(0xEF) . chr(0xBB) . chr(0xBF);
			/* vars for export */
			// database record to be exported
			$db_record = 'Liste_Noms';
			// optional where query
			$where = 'WHERE 1 ORDER BY 1';
			// filename for export
			$csv_filename = 'OSL_'.$db_record.'_'.date('Y-m-d').'.csv';
			$csv_export = '';
			$field = mysqli_field_count($dbconnect);
			// create line with field names
			for($i = 0; $i < $field; $i++) {
				$csv_export.= mysqli_fetch_field_direct($ress, $i)->name.';';				
			}
			// newline
			$csv_export .= PHP_EOL;
			// loop through database query and fill export variable
			while($row = mysqli_fetch_array($ress)) {
				// create line with field values
				for($i = 0; $i < $field; $i++) {
					$csv_export.= '"'.$row[mysqli_fetch_field_direct($ress, $i)->name].'";';
				}
			// newline 
			$csv_export .= PHP_EOL;
			}

			// ajout BOM au fichier pour passage en UTF8-BOM
			// pour MS Excel (Byte Order Mark)
			// compatibilité MS Excel Windows 
			$csv_export = $bom . $csv_export;
			
			// Export the data and prompt a csv file for download
			header("Content-type: text/x-csv; charset=utf-8");
			header("Content-Disposition: attachment; filename=".$csv_filename."");
			echo($csv_export);

=> cela fonctionne nickel sur le DSM.

MAIS :

faisant quelque fois des essais sur le Syno, j’ai installé le site à l’identique sur un Rasp Pi 3B+ pour pouvoir basculer au cas ou… Après quelques réglages (wordpress, nginx, php) tout fonctionne à merveille et à l’identique, … sauf cet export csv !!

Symptôme : Excel me dit « fichier corrompu », et quand je regarde de plus près, je m’apperçois que le fichier csv transféré contient une première ligne « parasite » :

image.png.bde047951b2a66bc40ab6fcb0964ecfc.png

Ce sont cette tabulation et « LF » en ligne 1 qui empêche Excel d’ouvrir le fichier. (alors que OpenOffice Calc s’en moque royalement et ignore cette ligne)

Le même code sur le Syno donne un résultat propre, sans cette première ligne.

Je crois avoir à peu près tout essayé pour supprimer cette ligne parasite (text/csv, application/csv, fputcsv, trim, ltrim, …) Rien de fonctionne.

La seule configuration que j’ai réussi à faire tourner sur le Pi, c’est un mettant un lien de chargement sur le site. Soit une syntaxe de ce type :

file_put_contents($csv_filename, $csv_export);
header('Location: http://pisl.ndd.tld/'.$csv_filename.'');

qui donne le lien de chargement du fichier à rapatrier. Toute autre méthode a échoué et m’a toujours mis ces 2 octets d’entête parasites (0x09 0x0a càd TAB & LF). En faisant une capture réseau, j’ai confirmé que c’est bien au départ, sur le Rasp Pi, que se produit l’ajout des ces 2 octets, phénomène qui n’apparait pas lorsque le même code est hébergé sur le NAS Synology.

Je cherche toujours quelle est la différence de config. qui pourrait expliquer ce comportement bizarre :

PHP7.3 d’un côté, PHP7.4 de l’autre ? LANG=en_US.utf8 d’un côté, LANG=fr_FR.UTF8 de l’autre ?

Si vous avez déjà croisé ce genre de problème, je serai heureux de partager.
Merci
Bruno78

Bonjour,
après de plus amples tests, il semble que ce ne soit pas un problème de version , mais plutôt un problème de configuration. En effet, j’ai réduis les fichiers au plus simple pour isoler le problème, et il se trouve que ces 2 octets supplémentaires 0x09 & 0x0A sont insérés en début de fichier lorsque le script se trouve dans l’arborescence Wordpress. Si on place le même fichier en dehors de cette arborescence, alors tout va bien.
Je pense donc que c’est un problème de paramètrage nginx / php / wordpress … . Mais pas identifié pour autant !
Bruno78

Problème résolu :
il s’agissait d’un caractère « blanc » (espace) qui était placé après une balise PHP fermante d’un fichier include. Ce caractère était interprété et pris en compte dans la commande « echo » du programme principal.
Bruno78