OVH Cloud OVH Cloud

existence & taille fichier client

15 réponses
Avatar
Asterbing
Y a t-il un moyen de tester l'existence et la taille d'un fichier client
avant upload ? -e et -s agissent côté serveur uniquement.

Ceci pour éviter le trafic inutile (upload, test sur serveur, puis
unlink si trop gros) et rendre compte à l'utilisateur au plus vite
(l'upload jusqu'à la taille limite autorisée pouvant prendre un certain
temps dans certains cas ; exemple : si j'accepte des fichiers de
plusieurs dizaines de Mo max).

10 réponses

1 2
Avatar
Paul Gaborit
À (at) Fri, 14 Apr 2006 13:58:28 +0200,
Asterbing écrivait (wrote):
Y a t-il un moyen de tester l'existence et la taille d'un fichier client
avant upload ? -e et -s agissent côté serveur uniquement.


Non. On ne pas peut faire confiance a priori aux données provenant du
client. De plus, le client lui-même peut ne pas connaitre la taille de
l'upload (ex: serveur de fichiers qui ne donne pas la bonne taille,
flux de données externes, fichier fifo, etc.).

Ceci pour éviter le trafic inutile (upload, test sur serveur, puis
unlink si trop gros) et rendre compte à l'utilisateur au plus vite
(l'upload jusqu'à la taille limite autorisée pouvant prendre un certain
temps dans certains cas ; exemple : si j'accepte des fichiers de
plusieurs dizaines de Mo max).


La seule chose qu'on peut faire est effectivement de placer une taille
maximale (c'est même très fortement conseillé !). Avec le module CGI,
il faut positionner :

$CGI::POST_MAX = 1024 * 100; # max 100K posts

(extrait de 'perldoc CGI'.)


--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Asterbing
In article ,
says...
Non. On ne pas peut faire confiance a priori aux données provenant du
client. De plus, le client lui-même peut ne pas connaitre la taille de
l'upload (ex: serveur de fichiers qui ne donne pas la bonne taille,
flux de données externes, fichier fifo, etc.).



Bon, limiter (arrêter) l'upload sur une limitre, OK, mais ça ne réduit
pas le trafic et ne permet pas à l'utilisateur qui soumet sont fichier
de savoir rapidement s'il est ou non trop gros.

Prenons un cas extrême : je mets une limite de taille à 100Mo et
l'utilisateur me soumet un fichier de 101Mo. Il aura uploadé 100Mo pour
rien et aura attendu plusieurs minutes pour le savoir.

Avatar
Paul Gaborit
À (at) Fri, 14 Apr 2006 16:33:38 +0200,
Asterbing écrivait (wrote):
Bon, limiter (arrêter) l'upload sur une limitre, OK, mais ça ne réduit
pas le trafic et ne permet pas à l'utilisateur qui soumet sont fichier
de savoir rapidement s'il est ou non trop gros.


Et non...

Prenons un cas extrême : je mets une limite de taille à 100Mo et
l'utilisateur me soumet un fichier de 101Mo. Il aura uploadé 100Mo pour
rien et aura attendu plusieurs minutes pour le savoir.


Ben oui...

Peut-être un petit message "Pas de fichier > 100Mo" clignotant en
rouge juste à côté du bouton "Soumettre" ? Mais ça ne fait que
reporter la responsabilité du problème de l'administrateur vers
l'utilisateur (qui, en général, ne sait pas comment connaître la
taille d'un fichier).

De toutes manières, permettre l'upload de fichier aussi gros est
toujours problèmatique. Exemple: la connexion tombe à 99Mo. Il n'y a
aucune psosibilité de reprise. Il faut tout renvoyer.

Bon, en fait, tout n'est pas perdu. Le protocole HTTP prévoit un champ
"Content-Lenght" (dans les réponses comme dans les requêtes) qui
devrait être renseigné par les navigateurs bien élevés (lorsqu'ils le
peuvent) et que le module CGI prend en compte pour refuser un POST si
la taille est trop grosse.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Asterbing
In article ,
says...
Bon, en fait, tout n'est pas perdu. Le protocole HTTP prévoit un champ
"Content-Lenght" (dans les réponses comme dans les requêtes) qui
devrait être renseigné par les navigateurs bien élevés (lorsqu'ils le
peuvent) et que le module CGI prend en compte pour refuser un POST si
la taille est trop grosse.



Ah, ça ça m'intéresse, Paul. Quelqu'un m'en parle aussi (Gunnar H.) sur
comp.lang.perl.misc (où je suis par ailleurs en train de me faire jeter
à tout va sous prétexte que ma question n'est pas orienté pure Perl),
mais je dois avouer que je ne perçois pas tout sur la manière d'utiliser
ce "Content-Length".

Est-ce que les navigateurs majeurs du moment le renseignent ?

Est-ce que je pourrais écrire une sorte de sub de faux upload qui ne
ferai que démarrer l'upload, juste pour voir si l'accès au fichier
client est ok et si sa taille ne dépasse pas la limite ?

Avatar
Paul Gaborit
À (at) Fri, 14 Apr 2006 19:25:48 +0200,
Asterbing écrivait (wrote):
Ah, ça ça m'intéresse, Paul. Quelqu'un m'en parle aussi (Gunnar H.) sur
comp.lang.perl.misc (où je suis par ailleurs en train de me faire jeter
à tout va sous prétexte que ma question n'est pas orienté pure Perl),
mais je dois avouer que je ne perçois pas tout sur la manière d'utiliser
ce "Content-Length".

Est-ce que les navigateurs majeurs du moment le renseignent ?


Je pense qu'ils le font quand ils le peuvent : s'ils peuvent calculer
à l'avance la taille exacte des données qu'ils envoient... Mais
j'avoue que je n'ai jamais testé. Pour vérifier avec firefox, vous
pouvez installer une extension appelée 'http live header' (ou un truc
du genre) qui vous le dira. Pour le savoir pour tous les navigateurs,
il doit y avoir des forum plus adaptés...

Est-ce que je pourrais écrire une sorte de sub de faux upload qui ne
ferai que démarrer l'upload, juste pour voir si l'accès au fichier
client est ok et si sa taille ne dépasse pas la limite ?


C'est exactement ce que fait le module CGI si la taille maximale de
POST est définie (comme je le disais dans ma première réponse) : il
stoppe l'upload dès qu'il a reçu la valeur de 'Content-Length' trop
grande.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Asterbing
In article ,
says...
C'est exactement ce que fait le module CGI si la taille maximale de
POST est définie (comme je le disais dans ma première réponse) : il
stoppe l'upload dès qu'il a reçu la valeur de 'Content-Length' trop
grande.



Bon, je suis en train d'aller vers cette voie. Merci Paul.

Par contre, pour revenir sur ce Content-Length, tous les exemples que
j'ai pu lire sur le web depuis démarrage de ce fil semblent l'utiliser.
Quasiment tous commencent par quelque chose comme : "read(STDIN, $buff,
$ENV{'CONTENT_LENGTH'});"

[j'ai d'ailleurs lu ds votre traduction de la doc Perl que vous
préconisiez de tester le retour du read]

Alors, comment ce fait-il si ce Content-Length n'est pas fiable ?

Bon, j'ai une autre question concernant le parsing ligne à ligne, mais
j'ouvre un autre fil pour ça ("CRLF selon OS") car ça me semble plus
général que le présent fil.

Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 15:42:46 +0200,
Asterbing écrivait (wrote):
Par contre, pour revenir sur ce Content-Length, tous les exemples que
j'ai pu lire sur le web depuis démarrage de ce fil semblent l'utiliser.
Quasiment tous commencent par quelque chose comme : "read(STDIN, $buff,
$ENV{'CONTENT_LENGTH'});"


Si vous voulez rentrer à ce niveau de détail, il va vous falloir
comprendre le protocole HTTP et le "protocole" CGI. En HTTP, l'entête
Content-Length n'est pas obligatoire. En CGI, il est absolument
requis. C'est le serveur Web qui complète l'information lorsqu'elle
manque. Ce qui signifie que si le serveur reçoit une requête sans
Content-Length, il attendra d'avoir reçu toute l'info avant d'activer
le programme CGI.

Alors, comment ce fait-il si ce Content-Length n'est pas fiable ?


S'il existe, il est fiable en CGI comme en HTTP. Il existe toujours en
CGI mais pas en HTTP.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 16:53:25 +0200,
Paul Gaborit écrivait (wrote):
Alors, comment ce fait-il si ce Content-Length n'est pas fiable ?


S'il existe, il est fiable en CGI comme en HTTP. Il existe toujours en
CGI mais pas en HTTP.


Ce n'est même pas sûr en CGI :

Servers MUST provide this metavariable to scripts if a "Content-Type"
field was present in the original request header. If the server
receives a request with an attached entity but no "Content-Type"
header field, it MAY attempt to determine the correct datatype, or it
MAY omit this metavariable when communicating the request information
to the script.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>


Avatar
Asterbing
In article ,
says...
Si vous voulez rentrer à ce niveau de détail, il va vous falloir
comprendre le protocole HTTP et le "protocole" CGI.


Jour après jour, bien sûr. Au sujet de vos guillemets pour désigner le
"protocole" CGI, n'est ce pas plus proche d'une API ? Ou est-ce quelque
chose de si hybride qu'aucune désignaton ne lui corresponde vraiment ?

En HTTP, l'entête Content-Length n'est pas obligatoire. En CGI, il est absolument
requis. C'est le serveur Web qui complète l'information lorsqu'elle
manque. Ce qui signifie que si le serveur reçoit une requête sans
Content-Length, il attendra d'avoir reçu toute l'info avant d'activer
le programme CGI.




Très intéressant Paul : voilà l'info essentielle. Donc, au positif : je
suis sûr d'avoir toujours ce Content-Length. Au négatif : lorsque je
l'ai, toutes les data du fichier à uploader sont déjà transmises et je
n'ai pas vraiment d moyen d'alerter l'utilisateur d'un fichier trop gros
avant ça.

Avatar
Paul Gaborit
À (at) Wed, 19 Apr 2006 17:49:42 +0200,
Asterbing écrivait (wrote):
Au sujet de vos guillemets pour désigner le "protocole" CGI, n'est
ce pas plus proche d'une API ? Ou est-ce quelque chose de si hybride
qu'aucune désignaton ne lui corresponde vraiment ?


C'est une interface de communication. On ne peut donc pas vraiment
l'appeler "protocole".

Très intéressant Paul : voilà l'info essentielle. Donc, au positif : je
suis sûr d'avoir toujours ce Content-Length.


Ce n'est pas sûr que cette information soit disponible (dixit les
spécifications CGI 1.1). Dans ce cas, pas d'autres solutions que de
recevoir l'ensemble des données...

Par contre, si vous l'avez, il y deux cas : soit c'est le navigateur
qui l'a envoyée et vous pouvez la recevoir (via le serveur HTTP) avant
même que tout le reste de la requête soit envoyée, soit c'est que le
serveur l'a calculée lui-même et qu'il a donc déjà tout reçu....

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

1 2