Aller au contenu

Téléchargement fichier corrompu


salcamden

Sujets conseillés

Bonjour,

J'ai un petit soucis avec le téléchargement d'un fichier. Je m'explique :

  1. Je créé un fichier .zip à l'aide de la librairie PclZip
  2. je teste le fichier .zip généré en le récupérant via FTP : pas de problême, l'archive s'ouvre sous windows
  3. je désire récupérer le zip à la volée, j'envoie donc les headers, et je lis le fichier en sortie.
  4. je teste le fichier récupéré de cette façon : le fichier est 'non valide'

Pour info, les deux fichiers ont le même nombre d'octet, mais les MD5 sont différentes.

voici la portion de code dont je me sert pour envoyer le fichier :

// Transfert du fichier

/*$file = './_tmp/'.$tmp_nom_global.'.zip';
readfile($file);*/

$fichier = './_tmp/'.$tmp_nom_global.'.zip';

// Nous extrayons les informations grâce à $fichier
$fichier_nom = basename($fichier);
$fichier_taille = filesize($fichier);
//$fichier_mime = mime_content_type($fichier);

$file = fopen($fichier,'rb');
$data = fread($file,filesize($fichier));
fclose($file);


// téléchargement du fichier
//header("Content-disposition: attachment; filename=$fichier" );
header("Content-Type: application/octet-stream" );
//header("Content-type: application/force-download");
header("Content-Disposition: attachment; filename=archive.zip");
header("Content-Description: File Transfert" );
header("Content-Transfer-Encoding: binary" );
header("Content-Length: $fichier_taille" );
header("Pragma: no-cache" );
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" );
header("Expires: 0" );

echo $data;
//readfile($fichier);

J'ai lu de tout concernant les headers à envoyer.

Si quelqu'un a une (bonne) idée.

Merci d'avance.

:cool:Damien

Modifié par salcamden
Lien vers le commentaire
Partager sur d’autres sites

Bonsoir,

pour ma part je n'enverrais pas le "Content-length" et ferais simplement un readfile après l'envoi des entêtes ; toutefois je ne pense pas que ce soit ce qui pose soucis.

De plus, je ne connais pas vraiment les entêtes Content-Description, Content-Transfer-Encoding, t'es certain de ton coup là ?

Sinon le transfert tu le fais comment, via un navigateur ?

Lien vers le commentaire
Partager sur d’autres sites

Salut,

Ben le Content-Length j'aime bien, ça permet de spécifier au navigateur (réponse à la deuxième question) la taille du fichier à télécharger, mais c'est optionnel.

Comme tu m'as mis le doute avec les headers, j'ai testé avec les header 'minimaux, soit :

Content-Disposition: attachment; filename=archive.zip
Content-Type: application/octet-stream

et j'ai retesté avec

Content-Disposition: attachment; filename=archive.zip
Content-type: application/force-download

Mais rien n'y fait...

N'y a-t-il pas un problême de EOF ou d'autre petites choses comme ça qui posent problême ?

Damien

Lien vers le commentaire
Partager sur d’autres sites

Le soucis en spécifiant soit même le "content-length" c'est qu'il peut être erroné (par exemple si un ob_gzhandler se déclenche derrière, même si ce n'est pas le cas ici), et ainsi causer une "corruption" du canal en cas de KeepAlive.

Mais pour en revenir à ton problème, je ne vois pas du tout de quoi ça pourrait venir. readfile() est heureusement "binary safe", et fonctionne d'habitude très bien, peu importe ce qu'on balance en sortie.

EDIT : et en utilisant un comparateur de fichier "binaire", tu notes quoi comme différence ?

Il me semble qu'un fichier ZIP contient la date de création ou un truc du genre, le checksum sera donc toujours différent, non ?

Modifié par Kioob
Lien vers le commentaire
Partager sur d’autres sites

@mjouan

Le serveur est un IIS (win) donc à priori, pas de problême de compatibilité avec mon client qui est sous XP (ceci veut-il dire que le zip ne fonctionnera pas sous LINUX ? (à tester)

@Kioob

J'ai essayé de faire l'output avec un

echo $data;

où $data est le contenu du .zip généré avec fread().

J'ai également testé avec

readfile($fichier);

mais ça ne donne rien.

Je vais tenter de générer le contenu du fichier avec un file(); mais j'ai peur que ce soit un peu bourrin (mes zip contiennent des mp3 et peuvent attaindre plusieurs dizaine de Mo). Pour le test, le zip fait 6 Mo, environ.

Merci en tout cas.

Bonne soirée.

Damien

Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Alors, il y a du nouveau,

J'ai testé l'appli sous linux (open Suse) et...

Ca marche, la piste de mjouan a l'air bonne. Comment y remédier ? Comment encoder un fichier binaire pour qu'il soit compatible avec win et Linux (je suppose que s'il est compatible linux, il l'est aussi pour mac ?)

De plus je n'avais pas vu ton EDIT : quel comparateur de fichier binaire utilisez-vous ?

Modifié par salcamden
Lien vers le commentaire
Partager sur d’autres sites

Amha readfile() est de loin la plus adaptée ici ; les autres fonctions feront toutes plus ou moins la même chose en moins bien (plus lentement et/ou en consommant plus de mémoire).

Si un script minimal avec seulement ça (absolument rien d'autre) ne fonctionne pas, c'est qu'il y a un gros pépin :

<?php
error_reporting( E_ALL );
header( "Content-Type: application/octet-stream" );
header( "Content-Disposition: attachment; filename=archive.zip" );
header( "Pragma: no-cache" );
header( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" );
header( "Expires: 0" );

readfile( '/chemin/vers/un/fichier.zip' );

Quand tu dis que ça ne donne rien, c'est que la sortie est "vide" ou bien que Windows n'arrive pas à décompresser le fichier obtenu ?

Essaye de comparer les deux fichiers en mode "binaire" (UltraEdit fait ça très bien), les différences devraient être marquantes.

EDIT : euh... un fichier binaire n'a absolument pas besoin d'une conversion Windows/Mac/Unix. Et readfile() ne fait pas de conversion non plus. Donc à moins que la source ait été uploadée de manière corrompue en ASCII via FTP, il n'y aucune raison de vouloir "convertir" un ZIP.

Modifié par Kioob
Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Quand je dis que ça ne donne rien, c'est que windows ne peut pas ouvrir l'archive (par contre, elle est bien "pleine" puisque son poids est rigoureusement égal à l'octet près à celui de l'archive qui n'est pas corrompue).

Je teste sous UltraEdit.

J'ai testé le code que tu m'as donné : le fichier est téléchargé (plein) par contre toujours non valide.

(Pour info le error_reporting( E_ALL ); écrit les erreurs dans un log ? Où est-il ?)

Merci, en tout cas !

Modifié par salcamden
Lien vers le commentaire
Partager sur d’autres sites

Le error_reporting change le "niveau de report" des erreurs, là il affiche la plupart des erreurs (par défaut les E_NOTICE ne sont pas affichés), mais il n'affiche pas pour autant les E_STRICT.

Je n'ai jamais vu readfile() corrompre un fichier, tu es certain que le chemin que tu indiques en paramètre à la fonction correspond au fichier que tu as transféré par FTP, en mode BINARY ?

Modifié par Kioob
Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Alors, après une comparaison avec UltraCompare :

le fichier corrompu commence par : ÔªøPK

le fichier valide par : PK

Il y a donc 3 caractères en entêtes qui corrompent le fichier.

A noter que le fichier récupéré grâce à ton code contient également les trois caractères.

Pour ta dernière question : oui, le fichier a été généré par un script php. Il est valide lorsque je le récupère via FTP. Il ne l'est pas lorsque je le transmet par mon script via HTTP.

Modifié par salcamden
Lien vers le commentaire
Partager sur d’autres sites

Bah t'avais pas dit qu'ils faisaient exactement la même taille ?

Je peux me tromper, mais j'ai l'impression que les deux premiers caractères correspondent à l'entête GZIP ; peux tu donner leur valeur héxadécimale stp ?

Edit : non, à priori ce n'est pas du tout ça :/

Modifié par Kioob
Lien vers le commentaire
Partager sur d’autres sites

Oui : EF BB BF

Il me semble que j'ai déjà vu ça sur le serveur d'un autre client (Windows lui aussi) qui me faisait un entête à chaque page : j'ai pas réussi à les virer.

Pour ce qui est de la taille, c'est normal (je faisais un fread($file,filesize($fichier)); pour extraire le contenu du zip à outputter : donc taille toujours égale, le fichier ne devais pas se terminer)

Par contre, comme ça ne fonctionne pas non plus avec le readfile(), ça ne vient pas de là.

Lien vers le commentaire
Partager sur d’autres sites

La représentation UTF-8 du BOM est la séquence d'octets EF BB BF

source : Google.

hu hu... ton script est en UTF-8 :P

Un peu plus d'info du coté de Wikipedia : http://fr.wikipedia.org/wiki/Marque_d%27ordre_des_octets

Ce serait donc ton éditeur qui ajoute (inutilement) cet entête afin d'indiquer que le fichier est en UTF-8... Bref si tu peux, change d'éditeur.

Modifié par Kioob
Lien vers le commentaire
Partager sur d’autres sites

Le BOM !!

Pourquoi ne pas y avoir pensé plus tôt !

C'est bon le fichier zip est valide.

Je ne me méfie jamais assez de l'encodage en UTF8.

Merci beaucoup de votre aide.

Bonne soirée

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...