LONGBLOB en fichier sans stockage intermédiaire

Eléphanteau du PHP | 17 Messages

24 juin 2013, 07:45

En gros j'ai un champ blob (image) en base contenant tous mes ficheirs.

Je veux via un header générer le fichier sans le stocker.

Mon code:

Code : Tout sélectionner

header("Content-Type: $ctype" ); //header("Content-type: application/force-download"); header("Content-Disposition: attachment; filename=$file"); header("Content-Description: File Transfert" ); header("Content-Transfer-Encoding: binary" ); header("Pragma: no-cache" ); header('Content-Length: ' . filesize($file)); header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" ); header("Expires: 0" ); ob_clean(); flush(); echo $recupere_doc['Contenu_Doc'];

J'ai effectué plusieurs tests.

En utilisant un fopen , j'ai créé le fichier puis rempli avec le contenu du champ image.
J'ai testé plusieurs méthodes et le résultat est le même...

Fichier corrompu dès qu'il y a une mise en forme, sur un texte .txt simple ca passe.

Que faire ?

ViPHP
ViPHP | 2577 Messages

24 juin 2013, 09:34

Bonjour,

Il faut utiliser un stockage binaire (interclassement ?) sur la base de données ou sur la table. En gros, il est possible que lors des manipulations de maj ou de lecture des octets du contenu soit modifié.

Pour tester, utilise une petite image et stocke sont contenu en base et créer un fichier à partir de la base. Tu pourras alors voir si le contenu est modifié en comparant les 2 fichiers.

Je ne peux malheureusement pas plus t'aider. En général, on évite de stocker des images en base. On stocke plutôt dans des fichiers et on garde uniquement le moyen de récupérer l'image dans la base.

Eléphanteau du PHP | 17 Messages

24 juin 2013, 09:51

Le stockage est même pire que ça puisque dans le champ de type image sont stockés tous les fichiers (pdf, excel,etc...) mais c'est pas moi qui décide ^^

Avec un soft développé en Delphi, les fichiers ressortent bien.
Il n'y a aucun traitement dans le code juste un ExtractFilePath puis TBlobField(FieldByName('Contenu_Doc')).SaveToFile(sPath);
A noter c'est sur SQL Server.

ViPHP
ViPHP | 2577 Messages

24 juin 2013, 10:07

Tu peux remplacer echo $recupere_doc['Contenu_Doc']; par readfile('un fichier');
Pour voir si ca marche avec le contenu d'un fichier.

Tu peux également vérifier le contenu recu avec un éditeur en enregistrant le contenu dans un fichier. Pas impossible qu'ob_clean() et flush() ne laisse pas passer des caractères en début ou fin.

Eléphanteau du PHP | 17 Messages

24 juin 2013, 10:27

Je viens de tester j'ai un fichier pdf sur le serveur, quand j'essaie de l'ouvrir via le read le fichier est corrompu encore...Si je l'ouvre sur le serveur manuellement pas de soucis...

Cela vient de l'apache ??

A noter le fichier sur le serveur fait 13Ko et sur le poste client une fois enregistré il fait 52Ko...

ViPHP
ViPHP | 2577 Messages

24 juin 2013, 10:53

Pour moi, ca vient de ob_clean() et flush().
Il doit y avoir des caractères qui sont quand même envoyé :
- message d'erreur PHP ou mysql ?
- saut de ligne ?
C'est ce qui pose problème généralement avec les images en général donc aussi avec des fichiers word ou pdf.

Supprimes l'envoi de l'image pour voir si quelque chose est envoyé en plus. A savoir, ob_end_clean() vide le buffer alors que ob_clean() j'ai un doute. Mais on ne voit pas d'ob_start() dans l'extrait de ton script.

Eléphanteau du PHP | 17 Messages

24 juin 2013, 11:05

Petite question quand je fais l'echo de mon contenu d'un docx à l'affichage j'ai (juste un morceau) :

Code : Tout sélectionner

PK!¬†PWŽÀ[Content_Types].xml ¢( ´”ËNÃ0E÷HüCä-Jܲ@5íÊ*QÄÚ8“Ö"~Èã¾þžqQ[µM¡°‰”Ø÷Þ3{:½¹®’)xTÖ䬝µXFÚB™QÎÞ‡Ïé=K0SˆÊÈِõº×WáÂ&¤6˜³qîs”cÐ3ëÀÐJi½^ýˆ;!¿Äøm«uÇ¥5LHCô`ÝΔbR…¤?§Ï+gF,y\í‹Q9S:êãw~Pá¡Â=‰p®RRªOM±Ç•®™2R.÷àX9¼!ð# qe
Cela me semble bizarre...

Eléphanteau du PHP | 17 Messages

24 juin 2013, 11:25

J'ai oublié de dire que les fichiers .log donc qui s'ouvrent dans le bloc note fonctionnent sans probleme.

ViPHP
ViPHP | 2577 Messages

24 juin 2013, 11:52

1) Cherche de caractère parasite :
echo '[debut]';
echo $recupere_doc['Contenu_Doc'];
echo '[fin]';
Pour voir s'il y a quelque chose avant ou après le contenu de ton fichier log.

ou

2) Contrôle du contenu
echo $recupere_doc['Contenu_Doc'];
$f = fopen('fichier.xxx','w');
fwrite($f,$recupere_doc['Contenu_Doc']);
fclose($f); 
Pour voir si fichier.xxx est bien formater (avec un docx ou autre en adaptant xxx) et s'ouvre bien

Eléphanteau du PHP | 17 Messages

24 juin 2013, 12:01

Bon j'avance....j'arrive à afficher un docx maintenant en faisant un readfile, par contre l'echo toujours le même problème...

Code : Tout sélectionner

$file = $recupere_doc['Nom_Doc']; ob_start(); header("Content-Type: $ctype" ); header("Content-Disposition: attachment; filename=$file"); header("Content-Transfer-Encoding: binary" ); header("Pragma: public" ); header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" ); header("Expires: 0" ); echo $recupere_doc['Contenu_Doc']; ob_flush(); flush(); ob_end_clean();
Mon code a un problème c'est pas possible !

Eléphanteau du PHP | 17 Messages

24 juin 2013, 12:03

Sur le docx il ne m'affiche pas debut et fin

Sur le serveur j'ai le même soucis le fichier est corrompu.

Eléphanteau du PHP | 17 Messages

24 juin 2013, 12:15

Pour résumer :

Si un fichier docx présent sur le serveur : affichage ok avec readfile()
Si on affiche le champ blob via un header/echo : erreur fichier corrompu, le texte est présent mais pas d'images.
Si je génère un fichier docx/pdf avec un fopen/fwrite : erreur fichier corrompu, le texte est présent mais pas d'images.

ViPHP
ViPHP | 2577 Messages

24 juin 2013, 13:30

Si je génère un fichier docx/pdf avec un fopen/fwrite : erreur fichier corrompu, le texte est présent mais pas d'images.
Pour moi, ca veut dire qu'il se passe quelque chose lors de la récupération de $recupere_doc['Contenu_Doc']. Comme cela marche avec delphi, je suppose que le stockage es ok et que c'est la lecture qui merde.

Comment fais tu la lecture ?
Tu peux regarder :
PDO::SQLSRV_ENCODING_BINARY (entier)
Spécifie que cette donnée est envoyée vers le (ou reçue du) serveur comme un flux d'octets, sans opérer d'encodage ou de traduction. Cette constante peut être utilisée dans les appels à PDOStatement::setAttribute, PDO::prepare, PDOStatement::bindColumn, et PDOStatement::bindParam.
source : http://php.net/manual/fr/ref.pdo-sqlsrv.php

Eléphanteau du PHP | 17 Messages

24 juin 2013, 13:35

Tu as la meme chose avec mssql ? ^^

Je récupère comme cela :

Code : Tout sélectionner

$recup_doc="SELECT * from table WHERE ID_Doc='$get_doc'"; $req_doc= mssql_query($recup_doc,$dblink) or die(mssql_error()); while($recupere_doc=mssql_fetch_assoc($req_doc)){ (instructions header) }

Eléphanteau du PHP | 17 Messages

24 juin 2013, 14:07

Oui cela doit venir de la, en base c'est en binaire et quand je fais un echo des fichiers docx/pdf et autres (sauf .log/.txt, ) je n'ai pas la même que que ce qu'il y a en base...

Je n'utilise pas PDO et arrivé au point ou j'en suis du dev (je continue un pré existant) je ne peux pas changer.