Upload de fichiers Ajax/Html5/jQuery

UploadAjaxABCI v6.6

auteur Alain Bontemps ABCIWEB
téléchargement du module d'upload Ajax

Fonctionnalités, installation

Fonctionnalités

  • Surpasse les limites serveur *
  • Retours d'informations en temps réel configurable
  • Styles et fonctions événementielles
  • Boutons de sélections configurables avec comportements drag and drop et/ou onclick
  • Vignettes de prévisualisation des images
  • Reprise d'upload possible pour les gros fichiers en utilisant la partie sauvegardée
  • Supporte l'upload multiple et multiple multiple
  • Exemples fonctionnels et prêts à l'emploi avec classes Php fournies côté serveur

- Compatible Navigateurs html5 "récents" IE >= 10.
- Option "by-pass" pour compatibilité avec les navigateurs obsolètes IE7, IE8 et IE9 (exemples fournis).

* Surpasse les limites relatives à l'upload des fichiers : "post_max_size", "upload_max_filesize" et "max_file_uploads" pour les serveurs Php.

Installation

Décompresser le fichier et placer le dossier Upload-Ajax-ABCI sur votre serveur.

Dans la plupart des cas vous pourrez faire fonctionner les exemples sans modification si vous utilisez Php côté serveur. En cas de problème, ou si vous utilisez un serveur de type FAI (exemple sites perso chez Free), consultez le paragraphe debug.

Pour utiliser la classe Javascript avec une autre technologie serveur voir le paragraphe Interactions Javascript/Serveur.

Conseils d'utilisation

Utilisez un des fichiers d'exemples customisés pour avoir une solution complète prête à l'emploi.

Pour faire votre propre module d'upload sur mesure, il est conseillé de commencer par lire ce tutoriel qui explique le code du fichier UploadAjaxABCI_Basique.php ainsi que les grands principes de fonctionnement de cet outil.

Vous constaterez avec le tutoriel et ce premier exemple que l'on peut obtenir un formulaire complet avec des fonctionnalités avancées avec simplement quelques lignes de code, aussi bien côté client que côté serveur.

La longueur de ce mode d'emploi tient au fait que les classes disposent de nombreuses options et méthodes pour répondre aux besoins les plus divers. Cependant quelques lignes suffisent pour un upload classique qui bénéficiera de toutes les fonctionnalités énoncées plus haut.

Ensuite se référer au fichier UploadAjaxABCI.php qui regroupe d'autres exemples de configuration de la classe Javascript et d'utilisation des styles css événementiels.

Le fichier UploadAjaxABCI_Custom.php est un exemple plus élaboré qui reprend les fonctionnalités déjà décrites et donne un exemple d'utilisation des fonctions Javascript événementielles.

Les autres fichiers d'exemples répondent à des besoins plus spécifiques.

Code couleur utilisé dans ce mode d'emploi :
Code HTML : classes prédéfinies permettant d'afficher des informations,
et attributs data-upabcicss-* permettant de définir des styles événementiels
Code JAVASCRIPT : paramètres de la classe Javascript,
et fonctions Javascript événementielles
Code PHP
Informations complémentaires

Notez que si certains fichiers d'exemples sont compatibles avec le navigateur IE7, ce mode d'emploi n'est compatible qu'à partir de IE8. Avec IE7 le menu se superposera sur la page, mais l'ensemble sera utilisable si vous réduisez suffisamment la largeur de la fenêtre du navigateur pour basculer la présentation en mode "téléphone mobile".

Principe d'affichage des informations

Les informations suivantes peuvent être affichées en temps réel durant l'upload en utilisant des classes css prédéfinies:
  • nom
  • taille
  • vignette de prévisualisation (si c'est une image)
  • progression graphique
  • progression textuelle
  • pourcentage
  • sauvegarde partielle effectuée
  • temps passé
  • temps restant estimé
  • status : en cours, ok, erreur, arrêt
D'autres informations sont accessibles par l'intermédiaire des objets passés en paramètre aux fonctions JavaScript événementielles qui renvoient toutes les propriétés disponibles sur les fichiers (ainsi leur contexte html). Par exemple :
  • Type, lastModified, dimensions des images
  • La vitesse d'upload, voir ce lien
  • Les propriétés EXIF des photos issues des appareils photo numériques, voir ce lien et le fichier "UploadAjaxABCI_Redimensions_Exif.php"
Cette liste n'est pas exhaustive car vous pouvez personnaliser le script selon vos besoins avec les fonctions événementielles.

1/ Classes CSS prédéfinies

Pour les informations disposant de classes prédéfinies (première liste du paragrpahe précédent), il suffit d'attribuer la classe css correspondante sur l'élément html de votre choix.

Une classe est également réservée pour indiquer le bloc html conteneur des informations spécifiques aux fichiers, et une autre pour afficher des informations d'ordre général (c.f. Tutoriel et code source des fichiers d'exemples).

Deux classes sont également réservées pour définir les commandes :
  • arrêter
  • arrêter tout
qui permettent l'arrêt optimisé afin de pouvoir effectuer une reprise d'upload ultérieure dans les meilleures conditions.

2/ Styles CSS événementiels

Pour rendre l'affichage html plus interactif, vous disposez de styles événementiels à définir selon vos besoins et qui seront appliqués en fonction des différentes étapes du traitement des fichiers et du formulaire.

3/ Fonctions Javascript événementielles

Vous disposez également de fonctions Javascript événementielles à définir selon vos besoins et qui seront exécutées à différentes étapes du traitement des fichiers et du formulaire.

4/ Exemple

Les styles css événementiels et les fonctions Javascript événementielles sont conçus pour fournir des commandes (Trigger) en fonction du traitement des fichiers. Ils ne sont pas indispensables pour l'upload, ni pour retourner les informations accessibles avec les classes prédéfinies.

Par exemple un élément html ayant la classe "UpAbci_name" permettra d'afficher le nom du fichier :

<span class="UpAbci_name"></span>

tandis que :

<span class="UpAbci_remainingTime"></span>

affichera le temps restant estimé.

A la fin de l'upload du fichier, l'affichage du temps restant ne sera plus utile. Je pourrais le laisser en place avec la valeur 0 mais si je veux épurer le résultat pour ne garder que les informations utiles, je peux supprimer cet affichage en utilisant le style css événementiel "data-upabcicss-result" qui sera activé dès la fin de traitement du fichier. Le code html deviendra donc :

<span class="UpAbci_remainingTime" data-upabcicss-result="display:none"></span>


Tout comme les styles événementiels, les fonctions Javascript événementielles sont également déclenchées en fonction des événements du formulaire et du traitement des fichiers. Elles permettent d'aller plus loin dans la programmation de la présentation et d'interfacer le script avec des scripts externes.
A ce sujet et en conplément des informations EXIF citées plus haut qui utilisent le plugin jQuery "fileEXIF", je donne plusieurs exemples de Crop + Upload qui utilisent le plugin "ImgAreaSelect".

Fichiers d'exemples

Fichiers d'exemples compatibles avec les navigateurs "récents" IE >= 10

  • Configuration de base
    UploadAjaxABCI_Basique.php

    Principe de base et styles css événementiels.

  • Des exemples progressifs plus complets
    UploadAjaxABCI.php

    Exemples de configurations et styles css événementiels.

  • Un exemple complet et customisé
    UploadAjaxABCI_Custom.php

    Styles css événementiels et utilisation des fonctions événementielles.

  • Idem ci-dessus avec vérification des fichiers déjà existants avant upload
    UploadAjaxABCI_Custom_VerifFileExist.php

    Styles css événementiels et utilisation des fonctions événementielles.
    Montre comment modifier les paramètres internes de la classe Javascript pour interdire l'envoi d'un fichier suite à un contrôle extérieur à la classe.

  • Redimensionnements d'images
    UploadAjaxABCI_Redimensions.php

    Redimensionnement et retour des éventuelles erreurs serveur. Le plus intéressant est dans le fichier d'upload côté serveur.

  • Redimensionnements d'images et propriétés EXIF des photos
    UploadAjaxABCI_Redimensions_Exif.php

    Idem ci-dessus plus utilisation des fonctions événementielles avec le plugin jQuery "fileEXIF" (installé),
    et ajouts d'informations spécifiques pour chaque fichier.

  • Crop d'images multiples
    UploadAjaxABCI_Crop_multiple.php

    Utilisation avancée des fonctions événementielles avec le plugin jQuery "imgAreaSelect" (installé),
    et ajouts de champs spécifiques pour chaque fichier.

  • Crop d'images multiples et champs multiples
    UploadAjaxABCI_Crop_multiple_multiple.php

    Utilisation plus avancée des fonctions Javascript événementielles avec le plugin jQuery "imgAreaSelect" (installé),
    et ajouts de champs spécifiques pour chaque fichier.

  • Upload multiple et contrôle de champs de type texte sur l'événement onsubmit
    UploadAjaxABCI_Controle_input_text.php

    Utilisation des fonctions Javascript événementielles.
    Exemple à consulter notamment si l'upload n'est pas l'objet principal du formulaire.
    Code côté serveur permettant entre autre d'associer un champ (ex : "titre") avec plusieurs fichiers envoyés successivement.
    Enregistrement en bdd et affichage d'un récapitulatif en retour.

  • Formulaire d'inscription et possibilité de joindre une photo avec recadrage (Crop) préalable
    UploadAjaxABCI_Inscription_Photo_Crop.php

    Utilisation des fonctions Javascript événementielles avec le plugin jQuery "imgAreaSelect" (installé).
    Exemple à consulter notamment si l'upload n'est pas l'objet principal du formulaire.
    Le "formulaire général" contient en fait deux formulaires qui sont envoyés successivement.
    Enregistrement des données en bdd suivi automatiquement par l'upload de l'image si un fichier a été sélectionné.
    Affichage d'un récapitulatif en retour.
    Centralisation de tous les messages d'information (côté client et côté serveur) dans un seul fichier.

Fichiers d'exemples compatibles avec les navigateurs IE >= 7

Les fonctionnalités pour les navigateurs >= IE10 sont entièrement préservées et identiques aux scripts ci-dessus.

Pour les navigateurs < IE10 uniquement, l'upload est fait en 100% php et ne bénéficie donc pas des fonctionnalités de la classe javascript. Il s'en suit que l'affichage des vignettes photo n'est pas disponible et que l'upload sera limité par les configurations serveur "post_max_size", "upload_max_filesize" et "max_file_uploads". Cependant ces erreurs seront gérées par la classe Php qui affichera un message adéquat et les fonctions de redimensionnements et autres fonctions de traitement serveur sont implémentées.

Faites attention d'utiliser une version jQuery 1.12 (comme celle utilisée actuellement), sinon les versions 3 et plus de jQuery ne sont compatibles qu'à partir de IE9.

Dépendances

Fichiers inclus dans ce module :
  • "UploadAjaxABCI.js" (classe Javascript d'upload)
  • "jquery.js", "jquery.imgareaselect.min.js" et "jquery.exif.min.js" (jQuery et plugins jQuery)
  • "UploadAjaxABCI_Php_Load.php" (ou équivalent, destination de la requête Ajax)
  • "UploadAjaxABCIServeur.php" (ou équivalent, classe d'upload serveur via Ajax)
  • "Php_Upload/Classes" (classes Php de services)

Configuration côté formulaire

Script serveur qui alimente le formulaire

Se référer au code source des fichiers d'exemples.
- Modifier éventuellement la variable $UpAbci_fragmentSize qui détermine la taille maximale des fragments. Par défaut, les fichiers en dessous de cette taille n'auront pas de sauvegarde temporaire (comportement modifiable avec l'option "saveAll" côté serveur). Plus cette taille est petite - minimum 1Mo - plus les sauvegardes seront fréquentes mais vous générerez plus de trafic et le temps d'upload total sera plus long.

Dans l'absolu le script peut fonctionner sans variables serveur transmises dans le formulaire puisque la taille maximale des fragments peut être renseignée par l'option de configuration Javascript config.fragmentSize, de même pour "$UpAbci_uniqidForm" qui défini une variable de session et peut être renseignée par l'option config.uniqidForm. Mais la variable de session est utilisée comme jeton de sécurité, et il est plus judicieux que la taille du fragment soit définie par le serveur. Dans la plupart des cas vous pouvez laisser le code inchangé.

Actuellement une valeur de fragment de 8Mo semble être une bonne moyenne. Avec une liaison adsl classique cela permet une sauvegarde toute les 1 à 3 minutes environ (dépend aussi du serveur cible).
Augmentez cette valeur selon les capacités de votre serveur si vous destinez principalement l'upload à des très gros fichiers pour diminuer le trafic serveur et accroître la vitesse globale des téléchargements.

Configuration du formulaire

1/ Le formulaire doit contenir un ou plusieurs champs de type file, avec ou sans attribut "multiple".

<input type="file" name="upload" multiple="multiple">

2/ La classe Javascript recherche également deux champs "input" nommés "UpAbci_fragmentSize" et "UpAbci_uniqidForm" :

<input type="text" name="UpAbci_fragmentSize" value="<?=$UpAbci_fragmentSize?>">
<input type="text" name="UpAbci_uniqidForm" value="<?=$UpAbci_uniqidForm?>">

Si ces champs sont vides ou inexistants la classe utilisera ses valeurs par défaut ou les valeurs configurées avec les options de configuration Javascript (c.f. remarque dans le paragraphe précédent).

- Vous pouvez ajouter d'autres champs dans le formulaire, ils seront automatiquement transmis au script serveur par la requête Ajax. Les champs avec la notation tableau sont également supportés. Côté serveur vous pourrez les récupérer en Php avec la fonction urldecode().

- Pour personnaliser le bouton de sélection des fichiers, utilisez l'option de configuration Javascript "config.customFileSelect" décrite plus bas.

- Pour ajouter des informations ou des champs spécifiques à chaque fichier en cas d'upload multiple, voir le code source du fichier "UploadAjaxABCI_Redimensions_Exif.php" ou des deux premiers fichiers de "Crop".

Classes prédéfinies pour l'affichage des informations

Toutes ces classes prédéfinies doivent se situer à l'intérieur du formulaire ou du conteneur des résultats de l'upload (correspondant au premier et troisième paramètre déclarés dans l'initialisation de la classe Javascript).

1/ Classes à définir sur des blocs html non spécifiques à chaque fichier

ClasseInformations / Comportements
UpAbci_infosServerRetourne des informations serveur d'ordre général.
UpAbci_stopAllComportement onclick.
Arrête le téléchargement du fichier en cours et les fichiers suivants en cas d'upload multiple (pas d'incidence sur les téléchargements précédents).

2/ Informations spécifiques à chaque fichier

ClasseConteneur des informations sur les fichiers
UpAbci_infosFileBloc indispensable pour l'affichage des informations spécifiques à chaque fichier.
Doit être inclus dans le bloc défini en troisième paramètre lors de l'initialisation de la classe Javascript. En cas d'upload multiple, ce bloc est dupliqué, en conséquence ne pas utiliser d'id à l'intérieur de ce bloc.
Important ! Les classes ci-dessous doivent être inclues dans le bloc html ayant la classe "UpAbci_infosFile".
ClasseInformation / comportement
UpAbci_nameNom du fichier.
UpAbci_sizeTaille du fichier.
UpAbci_progressionGProgression graphique dans une balise html <progress>
UpAbci_progressionTProgression textuelle
UpAbci_percentagePourcentage effectué
UpAbci_backupSauvegarde effectuée (0 si upload terminé ok)
UpAbci_durationTemps passé
UpAbci_remainingTimeTemps restant
UpAbci_statusStatus en cours, ok, arrêt, erreur, éventuellement complété côté serveur
UpAbci_stopComportement onclick
Arrêt de l'upload du fichier
UpAbci_imgPreviewAffiche l'aperçu si c'est une image dans la limite des configurations Javascript "config.imgPreviewMaxSize" et "config.imgPreviewMaxSizeTotal"
UpAbci_inputFileNameAffiche le nom de l'input de type file
Vous pouvez écrire des valeurs par défaut dans vos éléments html (ex : 0 Mo), elles seront remplacées automatiquement en temps voulu.

- Les valeurs par défaut des éléments utilisant les classes "UpAbci_progressionT", "UpAbci_backup" et "UpAbci_remainingTime" sont restituées quand l'upload est terminé.

- Les valeurs par défaut sont aussi analysées pour déterminer l'éventuel espacement à appliquer entre la valeur numérique et son unité correspondante. Si non renseignée ou si les premiers caractères ne sont pas numériques, l'espacement utilisé est celui de la configuration info.unitsSpacing ('&nbsp;' par défaut).

Styles événementiels

Les styles sont spécifiés avec l'attribut "data-upabcicss-...", et doivent être écrits en respectant la syntaxe classique, exemple :

<span style="display:none;width:15px;height:10px" data-upabcicss-result-ok="display:inline-block; background-color:green" data-upabcicss-result-error="display:inline-block;background-color:red"></span>

Ici j'ai créé un span caché par défaut qui s'affichera en vert uniquement si le résultat est ok et en rouge uniquement s'il y a une erreur dans l'upload.

1/ Styles applicables sur les blocs passés en paramètre dans l'initialisation de la classe Javascript

Les blocs sur lesquels pourront être appliqués ces styles événementiels par l'intermédiaire d'un attribut data-upabcicss-*, correspondent respectivement au bloc contenant le formulaire (avec le champ de type file) et au bloc contenant l'information des résultats de l'upload. Le second bloc n'étant pas nécessairement inclus dans le premier.

data-upabcicss-*Evénement déclencheur
select-filedes fichiers ont été sélectionnés
error-img-prev-totaltotal des images supérieur à "config.imgPreviewMaxSizeTotal"
submitle formulaire a été envoyé
submit-filedes fichiers ont été envoyés par le formulaire
upload-endfin de traitement de tous les fichiers
backup-endsauvegarde pour au moins un fichier en fin de traitement
form-endfin de traitement du formulaire avec ou sans fichiers traités
infos-serverle serveur a envoyé un message vers le bloc html ayant la classe "UpAbci_infosServer"
select-filedes fichiers ont été sélectionnés

2/ Styles applicables localement

Applicables sur le bloc éventuellement défini avec la classe UpAbci_infosServer lui-même (mais pas ses éléments contenus),
ainsi que sur le conteneur des résultats lui-même (troisième paramètre dans l'initialisation de la classe Javascript) et sur tous les blocs contenus dans le bloc d'information des fichiers défini avec la classe "UpAbci_infosFile".
A noter que les éléments html inclus dans le conteneur des résultats mais exclus de "UpAbci_infosFile" ne seront pas ciblés par les styles ci-dessous.
data-upabcicss-*Evénement déclencheur
error-img-prevtaille de l'image supérieure à "config.imgPreviewMaxSize"
error-img-prev-totaltotal des images supérieur à "config.imgPreviewMaxSizeTotal"
image-previewimage de prévisualisation disponible (si respect de config js)
error-usererreur utilisateur (taille, extension). Exclus "error-img-prev"
in-progressle fichier est en cours de traitement
backupsauvegarde partielle disponible (ancienne ou en cours)
resulttraitement du fichier terminé quelque soit la cause
result-stopfichier ou upload arrêté sur demande utilisateur
remaning-time-computes'applique après la durée de "config.remainingTimeCompute"
remaining-time-afters'applique après la durée de "config.remainingTimeDisplayAfter"
result-okupload terminé ok
result-partialupload terminé et sauvegarde existante
result-errorupload terminé erreur ou erreur utilisateur

3/ Ordre d'application des styles

Certains styles peuvent entrer en concurrence, ils sont appliqués dans l'ordre suivant :
  1. select-file
  2. error-img-prev
  3. error-img-prev-total
  4. image-preview
  5. error-user
  6. backup
  7. submit
  8. submit-file
  9. in-progress
  10. backup
  11. result
  12. result-stop
  13. remaining-time-after
  14. remaning-time-compute
  15. result-ok
  16. result-partial
  17. result-error
  18. upload-end
  19. backup-end
  20. form-end
- "backup" est appliqué avant "submit" pour les fichiers sélectionnés disposant d'une sauvegarde préalable, et également après le "submit" si le fichier dispose d'une sauvegarde durant le téléchargement.
- L'ordre d'écriture dans le html n'a aucune incidence.

4/ Styles configurables en Javascript

En complément de ces styles événementiels qui sont à utiliser dans le html avec l'attribut "data-upabcicss-*", vous disposez en complément des options de configuration Javascript "config.cssSubmitOn" et "config.cssFileSelectOn" (voir plus bas) pour formater les boutons d'envoi du formulaire et les champs de type file durant l'upload. L'upload terminé, les boutons retrouvent leur état initial.

Configuration de la classe Javascript UploadAjaxABCI

Trois paramètres sont attendus dans l'instanciation de la classe. Les deux premiers sont obligatoires, le troisième est optionnel mais indispensable pour l'affichage du retour des informations.

// Initialisation
var MyUpload = new UploadAjaxABCI('#param1', 'param2', '#param3');

/* si besoin en option, configuration des paramètres internes
et/ou des fonctions Javascript événementielles */

// ...

// Démarrage, DOM chargé
$(function(){MyUpload.Start()});
#param1 : Identifiant du formulaire cible avec notation id (#mon_id) ou class (.ma_class)
param2 : Destination de la requête Ajax (adresse du script d'upload côté serveur)
#param3: Bloc d'information html de l'upload avec notation id (#mon_id) ou class (.ma_class)
note : Le bloc défini par ce troisième paramètre sera réinitialisé automatiquement avec ses valeurs originales à chaque sélection de fichiers.
Exemple avec la configuration de deux paramètres :

// Initialisation
var up = new UploadAjaxABCI('#form', 'Php_Upload/upload.php', '.infos_form');

// Modification du retour du status ok (par défaut = 'Téléchargement ok')
up.info.status.ok = 'ok';

// Configuration d'un bouton personnalisé de sélection des fichiers (par défaut = non défini)
up.config.customFileSelect = ".bouton_fichiers";

// Pour terminer, utiliser la fonction Start() pour lancer le script, DOM chargé
$(function(){up.Start()});


Note : En cas de navigateur incompatible (IE < 10), le comportement peut être paramétré avec l'option "config.browserOutdeted=null;" pour envoyer le formulaire directement au script serveur mentionné dans l'attribut "action" du formulaire. Voir également la fonction événementielle "config.func_BrowserOutdeted" qui peut être exécutée dans ce cas de figure.

Options de configuration Javascript

Liste des paramètres configurables

L'ordre d'écriture des options n'a pas d'incidence.

Les méthodes ci-dessous sont listées avec les valeurs par défaut. Les valeurs numériques doivent être rentrées sans guillemets.

Il est vivement recommandé de paramétrer ces valeurs dans la configuration de votre script comme dans l'exemple précédent et les fichiers d'exemples. Evitez de modifier directement le code source de la classe Javascript "UploadAjaxABCI_DEV.js" ou sa version minifiée "UploadAjaxABCI.js".
config.ajaxTimeOut = 500
En milliseconde (sans unités), délai d'envoi de la requête Ajax, utile pour éviter de saturer un serveur local poussif. Evitez de mettre cette valeur à zéro. Je ne pourrai pas être tenu pour responsable si une sollicitation importante du système donne le coup de grâce d'un disque dur en cours d'agonie.
config.filesExtensions = []
Tableau des extensions autorisées (les variantes majuscules/minuscules sont automatiquement prises en compte). Si le tableau est vide aucune vérification n'est faite. Faire un contrôle supplémentaire côté serveur par sécurité (pas obligatoire mais très vivement conseillé).
config.filesExtensionsInput = []
Tableau des extensions autorisées pour chaque input du formulaire (les variantes majuscules/minuscules sont automatiquement prises en compte). La configuration requière le nom de l'input comme index. Par exemple si le champ se nomme "file1", la configuration pourra être : config.filesExtensionsInput["file1"] = ['jpeg','jpg','png']. Cette option peut être utile si plusieurs champs de type file sont inclus dans le même formulaire.
config.fileSizeMax = null
Taille maximale du fichier utilisateur. Si = 0 ou null aucune vérification n'est faite sur la taille du fichier. Accepte un nombre en octets ou une chaîne de caractère formatée avec les unités. Les espaces et la lettre "o" sont optionnels et le formatage ne tient pas compte de la casse. Par exemple 1073741824 = '1073741824o' = '1024Mo' = '1024 M' = '1048576k' = '1048576 Ko' = '1 go' = '1 G' (les nombres décimaux sont acceptés). Faire un contrôle supplémentaire côté serveur par sécurité (pas obligatoire mais très vivement conseillé).
config.customFileSelect = null
Un id ou une class ex "#mon_bouton" ou ".mon_bouton" pour identifier un bouton personnalisé de sélection de fichier. Ce bouton (ou ce lien) doit se situer à l'intérieur du formulaire indiqué en premier paramètre dans l'initialisation de la classe. Par ailleurs vous devez mettre un style "display:none" sur votre champ de type file. S'il existe plusieurs champs d'upload dans le même formulaire, utiliser une même classe pour définir les boutons (ou les liens) et ils seront affectés aux champs de type file dans l'ordre de leur écriture dans le html : le premier bouton sera affecté au premier champ, le second au second champ etc.
config.customDragAndDrop = true
Si et uniquement si "config.customFileSelect" a été défini : true permet le drag and drop, false annule ce comportement et donc seul le comportement onclick sera disponible.
config.cssSubmitOn = null
Styles avec notation standard (ex : "background:#ccc;border:1px solid blue;...") qui seront appliqués durant le traitement du formulaire sur les boutons de type "submit" inclus dans le formulaire. Les styles initiaux (initialement définis dans le html) seront restitués une fois le traitement terminé.
config.cssFileSelectOn = null
Styles avec notation standard (ex : "background:#ccc;border:1px solid blue;...") qui seront appliqués durant le traitement du formulaire sur les boutons de type "file" OU les boutons défini par "config.customFileSelect" inclus dans le formulaire. Les styles initiaux (initialement définis dans le html) seront restitués une fois le traitement terminé.
config.imgPreviewStartAuto = true
Booléen true ou false. true pour un affichage immédiat des vignettes images (si les contrôles sur le poids des images pour prévisualisation sont respectés). Si false vous pouvez utiliser la fonction "func_ImgPreviewStartAll()" pour faire afficher les vignettes dans le formulaire au moment voulu (voir le fichier d'exemple UploadAjaxABCI_Custom.php et les fichiers de Crop).
config.imgPreviewMaxSize = null
En Mo (sans unités). Poids maximal de chaque image pour prévisualisation. Si null, aucun contrôle individuel n'est fait avant la prévisualisation mais vous pouvez néanmoins contrôler le poids total de l'ensemble des images avec la configuration "config.imgPreviewMaxSizeTotal".
config.imgPreviewMaxSizeCancelAll = false
true ou false. Si true et que "config.imgPreviewMaxSize" est dépassé pour au moins une image, aucune vignette ne sera affichée.
config.imgPreviewMaxSizeTotal = null;
En Mo (sans unités). Poids total maximal de toutes les images pour prévisualisation. Si dépassé aucune vignette ne sera affichée. Si null, le contrôle n'est pas fait. Les images dépassant "config.imgPreviewMaxSize" ne sont pas totalisées puisqu'elles ne sont pas affichées. Par ailleurs, "config.imgPreviewMaxSizeCancelAll" à la priorité sur ce contrôle.
config.imgPreviewMaxWidth = 90
En pixels (sans unités), largeur maximale de l'aperçu image.
config.imgPreviewMaxHeight = 60
En pixels (sans unités), hauteur maximale de l'aperçu image.
config.infosRefresh = 1
En seconde (sans unités), fréquence de rafraîchissement des informations textuelles.
config.remainingTimeCompute = 10
En seconde, temps de calcul avant l'affichage du temps restant estimé. Si trop court le résultat n'est pas significatif. Durant l'attente c'est le paramètre "info.remainingTimeComputeWaiting" qui s'affiche. A l'issue de cette période, "data-upabcicss-remaning-time-compute" sera appliqué.
config.remainingTimeDisplayAfter = 30
En secondes (sans unités). Si le temps restant estimé pour l'upload du fichier est supérieur à cette valeur, "data-upabcicss-remaining-time-after" sera appliqué. Utilisée principalement pour ne pas faire afficher le temps restant (ou éventuellement la barre de progression) pour les petits fichiers.
config.recoveryBackupConfirm = false
Booléen true ou false si reprise automatique sans demande de confirmation.
config.submitWithoutFile = true
Booléen true ou false si le formulaire ne doit pas être envoyé en absence de fichiers valides. Si false et qu'aucun fichier valide n'est soumis, les fonctions Javascript événementielles "config.func..." concernant le suivi de la soumission du formulaire ne seront pas appelées, exceptée "config.func_FormEnd" si l'option ci-dessous est configurée à true. Cependant les fonctions événementielles précédent l'envoi du formulaire, y compris "config.func_onFormSubmit" seront exécutées si vous les avez définies.
config.submitWithoutFileFuncFormEnd = false
Sert uniquement dans le cas où config.submitWithoutFile = false. Si défini à true et qu'aucun fichier n'est soumis, permet néanmoins le déclenchement de la fonction événementielle "config.func_FormEnd(tableau)".
config.queryFormEnd = false
Booléen true ou false. Si = true, une requête additionnelle est envoyée au serveur pour indiquer la fin de traitement du formulaire avec comme paramètre un tableau d'information sur chaque fichier sélectionné (excepté si config.submitWithoutFile = false et qu'aucun fichier n'a été soumis). Si l'option est égale à true et config.submitWithoutFile = true et qu'aucun fichier n'est soumis un tableau restreint est renvoyé directement dans l'unique requête adressée au serveur.
config.BackupFormDependency = true
Booléen true ou false. "true" lie les possibilités de reprise d'upload du fichier à l'identifiant du formulaire et au nom du champ de type file. Voir cette note.
config.cookiePath = '/'
Path du cookie.
config.fragmentSize = 4194304
Taille du fragment en octet (sans unités) si le script ne trouve pas de champ nommé "UpAbci_fragmentSize" (défini avec une valeur non nulle et supérieure à 1048576) dans le formulaire. Si une valeur valide est trouvée dans le formulaire alors config.fragmentSize sera égal à cette valeur moins 10240. 10240 étant le nombre d'octets que prend arbitrairement la classe comme marge de sécurité pour que le post total (files + données textuelles) ne soit pas supérieur à la config Php "post_max_size" dans le cas où l'on choisirait une valeur de fragment égale à "post_max_size".
config.browserOutdeted = 'Navigateur obsolète incompatible'
Message pour les navigateurs incompatibles.
- Si non vide et différent de null, ce message s'affichera à la sélection des fichiers et à la soumission du formulaire en cas de navigateur obsolète. Le code javascript de la classe ne sera pas exécuté - excepté celui éventuellement défini par la fonction événementielle "config.func_BrowserOutdeted()" - et le formulaire ne sera pas envoyé.
- Si config.browserOutdeted = null, aucun message ne sera affiché en cas de navigateur obsolète. Le code javascript de la classe ne sera pas exécuté - excepté celui éventuellement défini par la fonction événementielle "config.func_BrowserOutdeted" - et le formulaire sera envoyé par défaut à l'adresse définie dans l'attribut html "action" du formulaire.
config.serverFatalErrorDisplay = true
Concatène les messages renvoyés par les erreurs fatales du serveur aux status Javascript "info.status.errorServer" et "info.queryEndErrorServer" (défini plus bas). Les messages renvoyés dépendent du script côté serveur.
Deux fonctions "cathErrorServeur()" et "setModeDebug()" sont disponibles dans la classe d'upload Php pour gérer le retour des erreurs fatales (cf fichiers exemples de redimensionnements et de Crop). Vous pouvez laisser true pour les exemples fournis car le script serveur ne renvoie que les messages personnalisés définis avec "cathErrorServeur()". "setModeDebug()" renvoie tout mais ne devrait pas être utilisé en production.
config.uniqidForm = this.SHA1(this.Uniqid('UploadAjaxABCI',true))
Valeur générée à l'affichage du script s'il ne trouve pas de champ nommé "UpAbci_uniqidForm" dans le formulaire.

Informations de retour
Annonces html (éventuellement vous pouvez rentrer du html plutôt que du texte plat)

info.status.ok = 'Téléchargement ok'
Complété éventuellement par un message provenant du script serveur d'upload.
info.status.inProgress = 'Téléchargement en cours'
Affichage du status durant le téléchargement.
info.status.stop = 'Arrêt'
Sur demande utilisateur.
info.status.errorSize = 'Dépassement de la taille maximale autorisée.'
Message si dépassement de "config.fileSizeMax".
info.status.errorExtension = 'Extension non valide.'
Message si l'extension ne fait pas partie du tableau "config.filesExtensions".
info.status.errorServer = 'Echec du téléchargement.'
Complété automatiquement par l'erreur serveur (si config.serverFatalErrorDisplay = true) ou par une erreur générée par le script Php d'upload.
info.remainingTimeComputeWaiting = 'calcul en cours'
S'affiche durant la période définie par la variable "config.remainingTimeCompute".
info.unitsSpacing = '&nbsp;'
Espacement par défaut entre les valeurs et leurs unités.
info.queryEndErrorServer = 'Echec dans la finalisation du traitement serveur. '
Annonce de fin de traitement du formulaire si config.queryFormEnd = true et erreur serveur lors de cette dernière requête. Complété automatiquement par l'erreur serveur si "config.serverFatalErrorDisplay = true"
Les options ci-dessous définissent l'annonce Javascript pour la reprise de la sauvegarde si "config.recoveryBackupConfirm = true"
info.recoveryBackupConfirm.name = 'Récupération du fichier : '
Annonce Javascript suivie du nom du fichier.
info.recoveryBackupConfirm.size = '\nSauvegarde en cours : '
Annonce (suite) suivie de la taille de la sauvegarde (\n pour retour ligne car la boite de confirmation est en Javascript).
info.recoveryBackupConfirm.message = '\n\nCliquez sur "OK" pour compléter ce fichier ou sur "Annuler" pour réinitialiser le téléchargement.'
Annonce (suite) dernière ligne.
- Remarque : la fonction de prévisualisation des images est assez gourmande en ressources (dépend de la résolution des images). Si vous utilisez le bloc de prévisualisation des images "UpAbci_imgPreview"" décrit plus haut et que ce script doit être optimisé également pour les smartphones, vous aurez peut-être intérêt de détecter le périphérique utilisé par le visiteur et le cas échéant, modifier la valeur des options de configuration "config.imgPreviewMaxSize" et / ou "config.imgPreviewMaxSizeTotal".

- Notez également que la valeur de "config.remainingTimeDisplayAfter" sera réellement supérieure à celle indiquée car la vitesse calculée au début du téléchargement pour estimer le temps restant est toujours surévaluée : avec une valeur de 30 secondes, le style défini par "data-upabcicss-remaining-timeafter" (décrit précédemment) ne sera peut-être pas appliqué pour des fichiers pouvant mettre jusqu'à un peu plus de 40 secondes pour se télécharger. Ce manque de précision est pratiquement sans importance car ce style est principalement prévu pour éviter d'afficher le temps restant - sans intérêt quand la progression graphique est suffisamment éloquente - pour les fichiers qui sont téléchargés rapidement.

Syntaxe des paramètres Javascript

  • Les chaînes de caractères doivent être entourées de guillemets.
  • Les valeurs numériques ainsi que les booléens true et false et les tableaux Javascript ne doivent pas être entourés de guillemets.
  • Il est vivement recommandé de mettre un point virgule à la fin de chaque instruction. Si cela n'est pas le cas dans la liste des options listées plus haut (pour alléger visuellement la présentation), tous les exemples de code adoptent cette convention qui permet d'éviter des bugs.

    Exemple de configuration :

// Initialisation
var up = new UploadAjaxABCI('#form', 'Php_Upload/upload.php', '.infos_form');

// Modification du retour du status ok (par défaut = 'Téléchargement ok')
up.info.status.ok = 'ok';

// Configuration d'un bouton personnalisé de sélection des fichiers (par défaut = non défini)
up.config.customFileSelect = ".bouton_fichiers";

// tableau des extensions autorisées
up.config.filesExtensions = ['jpg','jpeg','png'];

// En pixels (sans unités), largeur maximale de l'aperçu image.
up.config.imgPreviewMaxWidth = 110;

// En pixels (sans unités), hauteur maximale de l'aperçu image.
up.config.imgPreviewMaxHeight = 90;

// Le formulaire ne sera pas envoyé si aucun fichier n'est joint.
up.config.submitWithoutFile = false;

// Pour terminer, utiliser la fonction Start() pour lancer le script, DOM chargé
$(function(){up.Start()});

Les options de configuration de la classe Javascript ne sont pas toutes testées avant d'être utilisées. Si vous rentrer une chaîne de caractères rompue (pensez à échapper les guillemets internes) ou des valeurs numériques entourées de guillemets, vous obtiendrez le plus souvent un dysfonctionnement sans message d'avertissement préalable.

Fonctions Javascript événementielles

Voir le code source des fichiers de formulaires pour des exemples d'utilisation.
Le contenu des objets ou du tableau d'objets passés en paramètre dans les fonctions événementielles est détaillé dans le paragraphe suivant.
config.func_ImgPreviewLoadEach = null
Utilisation : config.func_ImgPreviewLoadEach = function(img,objet){};
Sera déclenchée pour chaque image de prévisualisation quand elle est chargée (voir les exemples de Crop). L'objet image est passé en premier paramètre et le second paramètre contient un objet d'informations générales sur le fichier.
config.func_FileSelectAllBefore = null
Utilisation : config.func_FileSelectAllBefore = function(event,tableau){};
Sera déclenchée à la sélection des fichiers AVANT l'affichage des informations. Retourne la sélection précédente si elle existe. L'objet "event" est passé en paramètre, ainsi qu'un tableau d'objets contenant des informations générales sur chaque fichier. En cas de sélections successives avant la soumission du formulaire, cette fonction peut être utilisée pour restaurer les informations des fichiers précédemment soumis (voir l'exemple UploadAjaxABCI_Crop_multiple_multiple.php).
config.func_FileSelectEach = null
Utilisation : config.func_FileSelectEach = function(event, objet){};
Sera déclenchée à la sélection de chaque fichier APRES l'affichage de ses informations (voir l'exemple UploadAjaxABCI_Crop_multiple.php). L'objet "event" est passé en paramètre ainsi qu'un objet contenant des informations générales sur le fichier.
config.func_FileSelectAll = null
Utilisation : config.func_FileSelectAll = function(event,tableau){};
Sera déclenchée à la sélection des fichiers APRES l'affichage des informations de tous les fichiers (voir l'exemple "UploadAjaxABCI_Custom.php" et les exemples de Crop). L'objet "event" est passé en paramètre, ainsi qu'un tableau d'objets contenant des informations générales sur chaque fichier.
config.func_onFormSubmit = null
Utilisation : config.func_onFormSubmit = function(event,tableau){};
Si définie, stoppe l'envoi du formulaire lors de sa soumission. Conçue pour faire des traitements/contrôles complémentaires. L'objet "event" est passé en paramètre ainsi qu'un tableau d'objets contenant des informations générales sur chaque fichier. Vous devrez utiliser la fonction "func_SubmitForm()" pour poursuivre le traitement et soumettre le formulaire.
config.func_FormSubmit = null
Utilisation : config.func_FormSubmit = function(event,tableau){};
Sera déclenchée à la soumission du formulaire (voir l'exemple "UploadAjaxABCI_Custom.php" et les exemples de Crop). L'objet "event" est passé en paramètre ainsi qu'un tableau d'objets contenant des informations générales sur chaque fichier.
config.func_FileInProgressEach = null
Utilisation : config.func_FileInProgressEach = function(objet){};
Sera déclenchée lors de la progression du téléchargement de chaque fichier suivant la fréquence du paramètre "config.infosRefresh". Toutes les informations en cours sont transmises en paramètre dans un objet.
config.func_FileEndEach = null
config.func_FileEndEach = function(objet, info_serveur, mixte_serveur){};
Sera déclenchée à la fin du traitement de chaque fichier (voir les exemples de Crop). Détail des paramètres "info_serveur" et "mixte_serveur" dans la fonction suivante.
config.func_FormEnd = null
Utilisation : config.func_FormEnd = function(tableau,info_serveur,mixte_serveur){};
Sera déclenchée à la fin du traitement du formulaire (voir l'exemple "UploadAjaxABCI_Custom.php" et les exemples de Crop).
Un tableau d'objets contenant des informations générales sur chaque fichier est passé en paramètre(cf. paragraphe suivant).
Le second paramètre "info_serveur" contient la réponse éventuelle du serveur transmise en Php avec la fonction addInfosServer() et qui s'affiche dans l'élément html (si défini) ayant la classe "UpAbci_infosServer". Peut contenir du texte ou du html. Si une erreur serveur intervient, "info_serveur" sera construit en fonction des options "config.serverFatalErrorDisplay" et "info.queryEndErrorServer" côté Javascript et de l'utilisation des fonctions "cathErrorServeur()" et "setModeDebug()" côté Php.
Le troisième paramètre "mixte_serveur" contient la réponse éventuelle du serveur transmise en Php avec la fonction addMixteServer(). Cette variable n'est pas affichée directement dans le html. Elle peut donc contenir du texte, du html ou encore un tableau que vous exploiterez comme bon vous semble.
config.func_BrowserOutdeted = null
Utilisation : config.func_BrowserOutdeted = function(){};
Sera déclenchée dès le chargement du script uniquement en cas de navigateur incompatible. Permet d'exécuter du code javascript pour les anciens navigateurs < IE10. Aucun autre code javascript ne sera exécuté par le script à la suite de cette fonction pour ces anciens navigateurs.

Fonctions relatives à la programmation événementielle

func_SubmitForm
Utilisation : func_SubmitForm();
NE DOIT PAS être configurée, mais uniquement utilisée comme commande pour poursuivre le processus normal et déclencher la soumission du formulaire. Cette commande ne fonctionne que si la fonction événementielle "config.func_onFormSubmit()" a été définie (voir plus haut) et est conçue pour être utilisée à l'intérieur de cette fonction. A noter qu'après l'utilisation de "func_SubmitForm()" le paramètre "tableau" envoyé par la fonction "config.func_onFormSubmit(event,tableau)" est réinitialisé (vide).
func_ImgPreviewStartAll
Utilisation : func_ImgPreviewStartAll();
NE DOIT PAS être configurée, mais uniquement utilisée comme commande pour déclencher l'affichage de toutes les images de prévisualisation. Fonctionne uniquement si config.imgPreviewStartAuto = false (voir l'exemple UploadAjaxABCI_Custom.php et les exemples de Crop) sinon la prévisualisation est automatique.
Contenu des objets spécifiques à chaque fichier passés en paramètre dans les fonctions événementielles
propriétécontenu
cook_name (1)le nom du cookie associé au fichier. Cette propriété est toujours définie même si le cookie n'est créé que pour les fichiers disposant d'une sauvegarde
fichier (2)(objet) contient la ressource file, le nom, la taille, le type... le nom du champ, et le détail des erreurs traitées en Javascript AVANT l'upload.
A noter que "upabciErrorUser" ne comptabilise pas "upabciErrorPreview"
img_heightuniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé)
img_prev_delayed0 si immédiat, 1 si l'affichage est différé, -1 si pas de prévisualisation
img_widthuniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé)
infos_html(objet html) le bloc d'information html ".UpAbci_infosFile"
iterationnombre d'itérations de la requête Ajax pour le fichier
join_file (3)Propriété libre (à définir selon vos besoins) spécifique à chaque fichier dont le contenu sera envoyé dans le paramètre "UpAbci_joinFile" de la requête Ajax
obj(objets html) tous les objets html d'informations de fichier ayant une classe ".Upabci_..."
qte_savequantité sauvegardée en continu
qte_save_inisauvegarde initiale trouvée à la sélection du fichier
qte_uploadquantité en cours
result (4)"ok_done", "backup_done", "error_done", "backup_fail", "error_fail" ou "0_0".
Préfixe = état du fichier, suffixe = état de la requête. "0_0" si pas traité.
stop0 ou 1 (sur demande utilisateur)
stop_all0 ou 1 (sur demande utilisateur)
time_endfin de l'upload en secondes et millièmes de secondes
time_startdébut de l'upload en millisecondes
Notes Importantes :
(1) Vous pouvez vous servir de la propriété "cook_name" (qui est toujours définie) comme identifiant du fichier. Sa composition est détaillée ici.
(2) Si vous souhaitez annuler la soumission d'un fichier, vous pouvez définir la propriété "fichier.upabciErrorUser" avec une valeur entière supérieure à 0, ex : "fichier.upabciErrorUser = 1". Un exemple est donné dans le code source du fichier UploadAjaxABCI_Custom_VerifFileExist.
(3) Voir paragraphe suivant.
(4) "result" qui indique le résultat final du fichier est renseigné au retour du traitement serveur sinon il vaut "0_0".

Ajout d'informations spécifiques à chaque fichier

Vous aurez parfois besoin de joindre des informations additionnelles spécifiques à chaque fichier. La propriété "join_file" des objets passés en paramètre dans la plupart des fonctions événementielles est réservée à cet effet.

La classe recherchera cette propriété, et si vous l'avez créée, elle sera transmise dans le paramètre "UpAbci_joinFile" de la requête Ajax que vous pourrez donc récupérer côté serveur.

Notez bien qu'aucun traitement n'est effectué sur le contenu de cette propriété puisqu'elle vous appartient. Utilisez la méthode "$.param()" de jQuery si vous souhaitez transmettre un tableau ou encore la fonction javascript "encodeURIComponent()" pour transmettre une simple chaîne de caractères.
En tous cas prenez soin que son contenu soit compatible avec la transmission de données dans une requête Ajax.

Le fichier "UploadAjaxABCI_Redimensions_Exif.php" et les exemples de crop donnent des exemples d'utilisation de cette propriété.

Fonctions Javascript annexes

Certaines fonctions internes de la classe Javascript pourront éventuellement vous être utiles, par exemple :
StopDrop (objet)
Accepte un objet html comme argument facultatif. Si non fourni l'évènement on drop est stoppé sur l'ensemble du document à l'exception des zones ciblées pour le drag and drop. Cette fonction est appliquée automatiquement si "config.customFileSelect" a été défini et que "config.customDragAndDrop" = true. Elle permet d'éviter que votre navigateur serve de visionneuse si les fichiers sont relâchés en dehors de la zone définie pour l'upload.
GetCssData (css_inline)
Demande une chaîne de caractère de type style css en ligne (ex : "cursor:wait;opacity:0.4"). Renvoie un objet directement utilisable par la fonction css de jQuery.
ReturnOctets (bytesFormate)
Renvoie des octets sans unités en fonction d'un nombre formaté avec des unités, ex : 5 Mo, 800 ko, 2.5Go, 1.2 T
FormateBits (bytes, espace)
Renvoie un nombre formaté avec des unités ex : 5 Mo, 800ko, 2.5Go, 1.2 T à partir d'un nombre d'octets sans unités. Fonction inverse de la précédente. Le second paramètre optionnel spécifie l'espace entre la valeur numérique et les unités.
Uniqid (prefix, more_entropy)
Génère un identifiant unique.
SHA1 (string)
Génère le sha1 de la chaîne passée en paramètre.
docCookies
Gestion des cookie, méthodes détaillées dans le fichier "UploadAjaxABCI_DEV.js"

Code Javascript complémentaire

- Si vous souhaitez ajouter des comportements onsubmit, utilisez la fonction Javascript "config.func_onFormSubmit" pour intercepter l'événement puis la fonction "func_SubmitForm" pour soumettre le formulaire. Cela permettra de poursuivre le traitement normal sur les fichiers.

- Si vous souhaitez ajouter des comportements onchange sur les boutons de sélection des fichiers, vous aurez des problèmes en cas de soumissions successives du formulaire sans rafraîchissement de la page. En effet pour compenser un bug IE10, le html du champ de type file est copié, supprimé puis recoller à chaque soumission du formulaire. Etant donné qu'il est impossible de cloner ce champ pour le bon fonctionnement du hack, les événements Javascript ne seront pas réintégrés.
Utilisez plutôt les fonctions Javascript "config.func_FileSelectEach" ou "config.func_FileSelectAll" dont les paramètres retournent l'objet "event" et des informations complètes sur tous les fichiers à chaque sélection de fichiers. Des exemples sont fournis dans les fichiers "...Custom...", "...Crop..." et "...Exif...".

- Notez également que les comportements éventuellement ajoutés sur les boutons (ou liens) d'arrêt des fichiers seront désactivés par la classe Javascript durant l'upload du formulaire qui imposera ses propres comportements pour optimiser une éventuelle reprise d'upload.
Voir les fichiers exemples de Crop et l'utilisation des fonctions Javascript événementielles "config.func_FileSelectEach" ou "config.func_FileSelectAll" (pour le fichier Crop_multiple_multiple) pour des exemples de programmation des boutons d'arrêt.

Utilisez prioritairement les styles événementiels ou les fonctions événementielles pour créer des comportements, ils sont conçus pour cela. Et n'oubliez pas de consulter le code source des fichiers d'exemples pour avoir un aperçu des possibilités.

Configuration côté serveur Php >= 5.4

Classes et code compatibles Php 7.1+
Fichiers exemples dans le dossier "Php_Upload".
L'adresse des fichiers cités dans cette rubrique est donnée par rapport à ce dossier.

Consultez le paragraphe Interactions Javascript/Serveur si vous souhaitez utiliser une autre technologie serveur que Php.

Configuration de la classe Php UploadAjaxABCIServeur

Vous constaterez avec le fichier "UploadAjaxABCI_Php_Load_Basique.php" qui est utilisé comme destination Ajax du formulaire "UploadAjaxABCI_Basique.php", que l'on peut configurer le script d'upload côté serveur avec quelques lignes de code (pour les cas basiques) en utilisant la classe Php "UploadAjaxABCIServeur".

Gardez bien à l'esprit que le script sera appelé plusieurs fois pour le traitement du même post, excepté en cas d'upload simple (non pas multiple) si la taille du fichier est inférieure à la taille d'un fragment ou si aucun fichier n'est joint au formulaire.

$up = new UploadAjaxABCIServeur($dossier_destination=null, $dossier_temporaire=null, $cookie_heures=null, $cookie_path=null, $verif_filesize_sup2Go=null)
$dossier_destination Dossier de destination de l'upload. Si ce paramètre vaut null ou est renseigné par une chaîne de caractère vide, la destination par défaut sera celle du dossier du script en cours d'exécution, soit actuellement "Php_Upload".
$dossier_temporaire Dossier où sont enregistrés les fichiers temporaires. Doit impérativement être renseigné pour permettre la fragmentation et la sauvegarde des fichiers temporaires.
$cookie_heuresLa durée de vie du cookie de sauvegarde en heures.
$cookie_pathLe path du cookie envoyé en Php. Doit pouvoir être récupéré par le script en Javascript.
$verif_filesize_sup2GoSuivant les serveurs, le contrôle de la taille d'un fichier supérieur à 2 Go peut retourner un résultat erroné. Pour cette raison, le contrôle de l'intégrité des fichiers qui compare la taille du fichier temporaire avec la taille du fichier originel, n'est pas faite automatiquement pour les fichiers supérieurs 2Go.
Si la fonction Php filesize() - utilisée pour ce contrôle par la classe Php - est efficace sur votre serveur pour des fichiers supérieurs à 2Go, il est recommandé de configurer ce dernier paramètre à true.
Note : L'adresse des dossiers passés en paramètre doit comporter un séparateur final, ex:

$dossier = '../Destination/';

Valeurs par défaut

Pour faciliter l'utilisation de la classe, et pouvoir accéder à ces paramètres de configuration dans d'autres contextes - par exemple la durée de vie du cookie et l'adresse du dossier temporaire sont également utilisés dans la classe "NettoyageTemp" - tous les paramètres de cette classe serveur ont des valeurs par défaut définis dans la fonction "getParamUploadAjaxABCIServeur" du trait "ParamsDefautServeur", cf. fichier "Classes/ParamsDefautServeur.php".

Les paramètres que vous passez dans l'initialisation de la classe "UploadAjaxABCIServeur" seront pris en compte s'ils sont strictement différents de la constante "null" (ou "NULL"), c'est à dire qu'une valeur renseignée et vide comme '' sera également prise en compte. Dans le cas contraire, si les paramètres sont non renseignés ou renseignés avec la constante "null", les paramètres définis dans "getParamUploadAjaxABCIServeur()" seront utilisés.

Dans les exemples de code, je définis pour plus de clarté le dossier de destination dans l'initialisation de la classe. Les autres paramètres sont normalement identiques pour les différents uploads.

Récupération des champs du formulaire

Vous pouvez récupérer les valeurs de vos champs input éventuellement ajoutés dans le formulaire avec la fonction Php "urldecode()".

$ma_variable = isset($_POST['ma_variable']) ? urldecode($_POST['ma_variable']) : null;

Les champs avec la notation tableau sont également transmis.
On peut traiter tous les éléments d'un tableau avec la fonction "array_walk_recursive" :

$tab_champ = isset($_POST['champ']) && is_array($_POST['champ']) ? $_POST['champ'] :[];
array_walk_recursive($tab_champ, function(&$item){$item = urldecode($item);});

La fonction "urldecode()" permet de décrypter l'encodage fait en Javascript - avec la fonction "encodeURIComponent()" utilisée en interne par jQuery - pour transmettre les variables du formulaire dans la requête Ajax. Si vous n'utilisez pas cette fonction ou une fonction permettant également de traiter l'encodage des URL, certains caractères spéciaux ou accentués ne seront pas affichés correctement.

Si vous avez utilisé la méthode "$.param()" côté javascript pour renseigner la propriété "join_file" spécifique à chaque fichier (par l'intermédiaire d'une fonction javascript événementielle), vous pouvez utiliser la fonction php "parse_str()" pour récupérer les données dans un tableau, par exemple :

$tab_join_file = [];
parse_str($up->getParam('join_file'),$tab_join_file);

Les données sont maintenant dans le tableau "$tab_join_file" et le décodage est fait en interne par la fonction "parse_str()". La méthode "getParam()" est détaillée ci-dessous.

Récupération des paramètres prédéfinis de la requête Ajax

Liste des paramètres spécifiques envoyés par la requête Ajax (pour information) :

IMPORTANT si vous souhaitez utiliser un autre langage serveur que PHP : les noms des variables Php ci-dessous correspondent aux noms des variables envoyées par la classe Javascript.

$UpAbci_form
Tableau de données. Il est renseigné dans tous les cas, excepté pour la requête complémentaire de confirmation de fin de traitement du formulaire qui est envoyée si et uniquement si l'option de configuration Javascript "config.queryFormEnd" = true. Dans ce cas et uniquement pour cette requête additionnelle, le tableau sera vide et vous pourrez récupérer les informations depuis "$UpAbci_formEnd" évoquée plus bas.
$UpAbci_formEnd
Uniquement disponible à la fin du traitement du formulaire si l'option de configuration Javascript config.queryFormEnd = true. Retourne un tableau de tableaux d'informations (1 pour chaque fichier) avec le même contenu que $UpAbci_form cité plus haut. Si aucun fichier n'est joint, le tableau renverra seulement les trois index "id_form", "uniqid_form" et "iteration_form".
Si l'option Javascript n'a pas été configurée ou si ce n'est pas la fin du traitement du formulaire $UpAbci_formEnd retourne un tableau vide.
$UpAbci_joinFile
Uniquement disponible si vous avez ajouté la propriété "join_file" aux objets passés en paramètre dans les fonctions événementielles. Permet de récupérer des informations spécifiques à chaque fichier, ajoutées optionnellement en javascript lors de l'upload.
$UpAbci_blobSlice
Renvoie "1" si le fichier est en plusieurs morceaux.
$UpAbci_fileEnd
Renvoie "1" si c'est la fin du fichier (dernière partie).
$UpAbci_fragment
Le fragment de ficher correspondant à $_FILES['UpAbci_fragment']
OU
La valeur 1 correspondant à $_POST['UpAbci_fragment'] si une sauvegarde complète est trouvée lors de la sélection du fichier et dans ce cas $_FILES['UpAbci_fragment'] n'est pas définie.
Les variables (propriétés de la classe serveur) $UpAbci_blobSlice, $UpAbci_fileEnd et $UpAbci_fragment sont en visibilité protected car vous n'en aurez pas besoin directement. De même une méthode "getParam ($index)" est prévue pour récupérer les valeurs des éléments du tableau $UpAbci_form ainsi que le contenu de $UpAbci_joinFile.

Liste des index du tableau $UpAbci_form :

Dans tous les cas(excepté pour l'éventuelle requête additionnelle)
id_formL'id du formulaire
uniqid_formL'identifiant unique du formulaire
iteration_formNombre d'itérations de la requête Ajax pour le formulaire (remise à zéro pour chaque nouvelle soumission du formulaire)
Si un fichier
est joint
au formulaire
(excepté pour l'éventuelle requête additionnelle)
input_nameNom de l'input de type file
cook_nameLe nom de l'éventuel cookie de sauvegarde (toujours défini)
nameLe nom du fichier
sizeLa taille du fichier
typeLe type du fichier
lastModifiedLa valeur de "lastModified"
qte_saveQuantité sauvegardée en continu
qte_uploadQuantité uploadée en continu
result (1)"ok_done", "backup_done", "error_done", "backup_fail", "error_fail", ou "0_0"
Préfixe = état du fichier, suffixe = état de la requête.
time_startDébut de l'upload
time_endFin de l'upload
iterationNombre d'itérations de la requête Ajax pour le fichier
join_file (2) Contenu brut de $UpAbci_joinFile. Aucun traitement n'a été effectué sur ce contenu. Il vous appartient d'utiliser les fonctions php "urldecode()" ou "parse_str()" ou autre, en fonction du format des données que vous avez ajoutées côté javascript.
(1) "result" est le résultat final renseigné en Javascript au retour de la requête Ajax. Sa valeur sera donc toujours 0_0 côté serveur excepté pour la dernière requête si vous configurez l'option config.queryFormEnd = true pour envoyer une requête additionnelle en fin de traitement du formulaire.

(2) Pour information, le tableau "$UpAbci_form" ne contient pas initialement l'index "join_file". La classe serveur l'ajoute automatiquement dans ce tableau à réception de la requête avec la valeur de $UpAbci_joinFile, pour que ce paramètre puisse être récupéré avec la méthode "getParam()", à l'instar des autres paramètres prédéfinis.

La méthode getParam ($index) de la classe d'upload Php retourne les valeurs du tableau "$UpAbci_form", sinon (si ce tableau est vide) retourne éventuellement les valeurs de "$UpAbci_formEnd[0]" pour les index "id_form", "uniqid_form" et "iteration_form".
Exemple :

$name = $up->getParam('name'); // retourne le nom du fichier ou false si l'index n'existe pas

Méthodes de la classe UploadAjaxABCIServeur

Ces méthodes de la classe Php sont utilisées et commentées dans le code source des fichiers d'exemples : UploadAjaxABCI_Php_Load_....php.

Pour plus de souplesse une classe "UploadABCIServices" regroupe des méthodes souvent utilisées dans les scripts d'upload. Cela permet d'instancier cette petite classe de services dans les scripts de formulaires côté client pour exploiter ses fonctionnalités. La classe "UploadAjaxABCIServeur" hérite de cette classe de services.

Méthodes spécifiques de la classe "UploadAjaxABCIServeur"

cathErrorServeur ($array_erreur)
cf gestion des erreurs fatales du serveur
setModeDebug()
cf gestion des erreurs fatales du serveur
getParam ($index)
Retourne les valeurs des éléments du tableau "UpAbci_form" envoyé par la requête Ajax.
getFileEnd ()
Retourne true si c'est la fin du fichier sinon false. Retourne indéfini si aucun fragment de fichier n'est joint dans la requête. A noter que cette fonction retourne la valeur UpAbci_fileEnd envoyée par Javascript avant tout traitement du fichier par le serveur.
Utilisez la fonction "getTempAdressFileComplete()" après la fonction "Upload()" pour avoir confirmation que le fichier est correctement enregistré dans le dossier temporaire du serveur ou "getTransfertOk()" après la fonction "Transfert ()" pour avoir confirmation que le fichier est transféré correctement dans son emplacement définitif.
saveAll ($value=true)
A utiliser impérativement AVANT la fonction "Upload()" sinon elle est inopérante. Cette fonction permet d'utiliser le répertoire temporaire pour stocker tous les fichiers y compris ceux dont la taille est inférieure à la taille des fragments (vous pouvez faire $up->saveAll(false) si vous souhaitez désactiver cette fonctionnalité après l'avoir activée).
getFragment ()
Retourne true si un fichier est joint dans la requête ou si une sauvegarde complète a été trouvée pour le fichier.
getFragmentSize ()
Retourne la taille du fragment. Ne pas utiliser pour tester la présence d'un fragment car si une sauvegarde complète est trouvée cette valeur sera définie à zéro. Seule l'utilisation de getFragment() doit être utilisée pour tester la présence d'un fichier joint dans la requête.
getcleanFileName()
Retourne le nom du fichier nettoyé.
getFileDestination ()
Retourne la destination avec le nom du fichier nettoyé soit $dossier_destination.$nom_fichier_nettoye
addInfosServer ($value)
Ajoute un message texte ou html dans le retour d'information général du formulaire ayant la classe UpAbci_infosServer. Pourra également être récupéré en second paramètre des fonctions Javascript événementielles config.func_FileEndEach et config.func_FormEnd
addMixteServer ($mixte)
Envoie un contenu texte, html ou un tableau de données qui pourra être récupéré en troisième paramètre des fonctions Javascript événementielles config.func_FileEndEach et config.func_FormEnd. N'affiche rien dans le html. Vous devrez exploiter ces données comme bon vous semble.
stopForm($query_end=false)
Stoppe la soumission du formulaire. Cette commande ne sort pas du script Php en cours, utilisez "exitReponseAjax()" par la suite.
Si l'option de configuration Javascript config.queryFormEnd = true l'éventuelle requête de confirmation de fin de formulaire sera envoyée uniquement si le paramètre $query_end = true.
exitStatusErreur($value)
Sort du script en ajoutant un message qui sera concaténé au statut info.status.erreur de la classe Javascript et envoyé dans le bloc html du fichier ayant la classe UpAbci_status". Ne transmet pas les éventuels messages précédemment ajoutés avec les fonctions "addInfosServer()" ou "addMixteServer()", pour ce faire utilisez plutôt la fonction "addStatusErreur($value)".
Upload()
Initialise l'upload du fichier ou du fragment de fichier et suivant les cas compile les fragments dans un fichier temporaire.
addStatusErreur($value)
Ajoute un message qui sera concaténé au statut info.status.erreur de la classe Javascript et envoyé dans le bloc html ayant la classe UpAbci_status. Ne sort pas du script, utilisez "exitReponseAjax()" par la suite.
A utiliser après la fonction "Upload()" si vous souhaitez préserver un fichier partiellement ou totalement téléchargé.
getTempAdressFileComplete()
A utiliser APRES la fonction "Upload"
Retourne l'adresse du fichier temporaire s'il est complet et valide sinon false
getTempAdressFile()
A utiliser APRES la fonction "Upload"
Retourne l'adresse du fichier temporaire. Peut être un fragment de fichier.
Transfert($file_destination=null)
Transfère le fichier uploadé et complet vers son emplacement définitif. Si aucun paramètre n'est passé en argument, $file_destination est construite avec le nom du fichier nettoyé et a donc la même valeur que "$dossier_destination.getCleanFileName()".
deleteCookieSave()
A utiliser lorsque que l'on ne souhaite pas utiliser la fonction Transfert() pour transférer le fichier vers son emplacement définitif cf Upload sans Transfert.
setTransfertOk()
A utiliser lorsque que l'on ne souhaite pas utiliser la fonction Transfert() pour transférer le fichier vers son emplacement définitif cf Upload sans Transfert.
addStatusOk($value)
A utiliser normalement APRES la fonction "Transfert()"
Ajoute un message qui sera concaténé au statut info.status.ok de la classe Javascript et envoyé dans le bloc html ayant la classe UpAbci_status.
getTransfertOk()
A utiliser APRES la fonction "Transfert()".
A le même effet que de tester le retour de la fonction Transfert(). Retourne true si le fichier est complet et a été déplacé avec succès vers son emplacement définitif.
exitReponseAjax()
Retour d'information INDISPENSABLE pour le script Ajax excepté si la fonction "exitStatusErreur()" a été utilisée. On peut alternativement utiliser la fonction "getReponseAjax()" suivant le contexte.
getReponseAjax()
Alternative à la fonction exitReponseAjax. Retourne les informations nécessaires pour le retour Ajax mais ne sort pas du script Php.

Méthodes héritées de la classe "UploadABCIServices"

cleanFileName($chaine)
Retourne $chaine après lui avoir appliqué le même filtre que celui utilisé par getCleanFileName()
getUniqid ()
Retourne un identifiant aléatoire unique
returnOctets ($val)
Retourne des octets depuis une chaîne formatée comme 25ko ou 100 Mo ou 1 g
verifExtensions($fichier,$extensions)
A utiliser AVANT la fonction "Upload" (si vous l'utilisez après, le fichier sera téléchargé dans le répertoire temporaire avant que le visiteur puisse avoir l'information)
renameIdenticName($adresse_fichier, $incr = false, $unix = false)
A utiliser AVANT la fonction "Transfert()" et de préférence après avoir vérifié que le fichier est complet afin de minimiser l'utilisation de cette fonction qui peut être assez gourmande en ressource (en fonction du nombre de fichiers du répertoire) si le deuxième paramètre est renseigné pour renommer les fichiers en mode incrémentiel.
Renomme le fichier téléchargé si un fichier de même nom existe déjà sur le serveur.
Par défaut la fonction ajoute un identifiant unique (uniqid) au nom des fichiers.
- Avec un second argument optionnel quelconque (ex : $up->renameIdenticName($destination_fichier,'incr');) le nom des fichiers est incrémenté.
- Un troisième argument optionnel casse sensitive est également disponible, mais à n'utiliser que sur les serveurs casse sensitive (NE PAS UTILISER AVEC LES SERVEURS WINDOWS).

Gestion des erreurs fatales du serveur

Voir exemple d'application dans le fichier :
"UploadAjaxABCI_Php_Load_Redimensions.php".

Les messages d'erreurs seront concaténés au message configuré par la classe Javascript avec "info.status.errorServer"

Si aucune des deux fonctions "cathErrorServeur()" ou "setModeDebug()" n'est utilisée, les erreurs fatales ne seront pas transmises et seul le message Javascript défini avec "info.status.errorServer" s'affichera.
setModeDebug()
Affiche les erreurs non catchées par la fonction "cathErrorServeur()". A n'utiliser qu'en phase de développement.
cathErrorServeur($tableau)
Demande un tableau en paramètre et permet de personnaliser le retour des erreurs fatales. L'index des valeurs est constitué par une suite de mots génériques renvoyés par l'erreur du serveur, et les valeurs sont constituées soit du message personnalisé à afficher, soit d'un tableau constitué du message personnalisé comme premier élément et de la valeur "true" (ou d'une valeur non nulle et différente de false) comme second élément pour indiquer de supprimer le fichier temporaire et l'éventuel cookie identifiant ce fichier.
Par exemple les erreurs lors des redimensionnements d'images proviennent la plupart du temps d'un dépassement des configurations serveur "memory_limit" et/ou "max_execution_time".
Les messages textuels renvoyés par le serveur commencent respectivement par :
'Allowed memory size ...' et 'Maximum execution time ...'.

On peut donc gérer ces erreurs avec le tableau suivant :

$tab_erreurs = array();

// le cookie et le fichier de sauvegarde seront supprimés
$tab_erreurs['Allowed memory size'] = array("Mémoire insuffisante, le fichier est trop gros pour être redimensionné.",true);

// le cookie et le fichier de sauvegarde seront préservés
$tab_erreurs['Maximum execution time'] = "Le temps d'exécution maximum du script est dépassé, rechargez votre image et réessayez !";

$up->cathErrorServeur($tab_erreurs);

Vous pouvez bien entendu compléter le tableau d'erreurs par autant de lignes que vous voulez.

Pour l'exemple ci-dessus je fais l'hypothèse (pas forcément juste) que si une erreur mémoire se produit lors du redimensionnement, il est inutile de réessayer donc je peux effacer le fichier temporaire et l'éventuel cookie enregistrant les coordonnées de la sauvegarde. Cela permet si besoin d'optimiser le nettoyage du dossier temporaire.
Par contre le dépassement de "max_execution_time" peut être dû à un serveur momentanément surchargé. On a donc peut-être intérêt de conserver le fichier éventuellement sauvegardé pour une nouvelle tentative. Cela permettra de le réutiliser directement lors du prochain chargement du fichier sans avoir besoin d'attendre pour son téléchargement.

Concernant les index du tableau, la fonction fait une recherche des mots constituant cet index dans le corps du message d'erreur renvoyé par le serveur avec "strpos($erreur_serveur,$index) !== false".
Vous devez donc rentrez une suite de mots génériques qui correspond au texte de cette erreur, suffisamment pour bien cibler l'erreur mais pas trop pour éviter les variables !

Je n'ai pas trouvé d'autre solution car la fonction "error_get_last()" de Php qui permet d'attraper les erreurs fatales ne renvoie aucun index correspondant à l'erreur (sinon le type qui est trop imprécis), mais simplement le texte de l'erreur. Il en résulte que si le message d'erreur Php venait à changer, l'erreur ne serait plus gérée par la fonction "cathErrorServeur()". Cependant l'expérience montre que ces messages d'erreur n'évoluent quasiment jamais au fil des versions Php. Et si c'était le cas, les conséquences seraient très limitées car l'erreur sera néanmoins interceptée. Simplement aucun message correspondant ne serait trouvé et seul le message configuré en Javascript par "info.status.errorServer" s'afficherait. L'information visiteur serait donc seulement moins précise, mais ce serait sans incidence sur la confidentialité ou la sécurité du script.

Note : la gestion de ces erreurs est surtout utile pour le debug avec "setModeDebug()" lors de la configuration du script Php, ou pour personnaliser les éventuels retours d'erreurs lors d'un traitement complémentaire à l'upload avec "cathErrorServeur()".
Concernant l'upload lui-même et donc si vous ne faites pas de traitement complémentaire, vous ne devriez plus avoir d'erreur une fois le script configuré puisque ce module surpasse les limitations serveurs spécifiques à l'upload avec la fragmentation.

La "seule" erreur possible restante est une perte de connexion (souvent après plusieurs heures d'upload en continu sur un serveur mutualisé). Dans ce cas la vérification du token échouera et vous devriez avoir le message d'erreur associé soit actuellement dans mes exemples :

"Connexion non valide ou perdue. Rafraîchissez la page et recharger votre fichier, si celui-ci dispose d'une sauvegarde automatique elle sera utilisée".

Visibilité des fichiers uploadés

En complément de la configuration des droits d'accès des dossiers, variables suivant les hébergeurs, certains hébergements (notamment OVH mutualisés) nécessitent d'attribuer des droits d'accès aux fichiers lors de l'upload pour autoriser leur accès depuis une adresse web :
//...
$transfert = $up->Transfert($destination_fichier);

/*
Si l'on doit indiquer les droits d'accès du fichier, par exemple 604, on peut faire :
*/
if($transfert && !@chmod($destination_fichier,0604))
{

/*
Si échec, envoi d'un message d'erreur défini dans la classe "Messages" :
"Echec de la configuration des droits d'accès du fichier."
*/
$up->exitStatusErreur(SetMessages::setMess('UpAbConfigChmod'));

}
//...
Des exemples sont donnés en commentaires dans les fichiers d'upload serveur.

Upload sans Transfert

Dans certains cas, vous pouvez avoir besoin d'exploiter le fichier uploadé sans nécessairement le sauvegarder sur votre serveur.

Tous les exemples d'upload côté serveur utilisent la méthode Transfert() qui transfère le fichier temporaire complet vers son emplacement définitif. Elle effectue de plus automatiquement deux tâches indispensables à la bonne continuité du script Javascript (côté client) :
  • L'enregistrement de l'état de l'upload dans le retour Ajax
  • L'effacement du cookie de sauvegarde du fichier en cours
De plus cette fonction efface implicitement le fichier temporaire du dossier temporaire puisqu'elle le transfère vers son emplacement définitif.

Si donc vous ne souhaitez pas utiliser la fonction Transfert() vous pouvez utiliser les méthodes setTransfertOk(), deleteCookieSave() et effacer le fichier temporaire pour réaliser les fonctions automatiques équivalentes.
A noter que contrairement aux deux premières fonctionnalités, l'effacement du fichier temporaire n'est pas indispensable à la bonne continuité des scripts. Mais si vous n'en avez plus besoin autant ne pas encombrer le serveur.
$dossier_destination = ''; // ce paramètre ne sera pas utilisé
$dossier_temporaire = '../Upload_Temp/';

//...

$up = new UploadAjaxABCIServeur($dossier_destination, $dossier_temporaire);

//...

$up->Upload();
$fichier_complet = $up->getTempAdressFileComplete();
if($fichier_complet != false)
{

/* ici vous pouvez utiliser le fichier temporaire "$fichier_complet" suivant vos besoins.
Cela pourrait être un fichier ".csv" servant pour alimenter une base de donnée, etc. */

// $bdd = C_PDO::getC();

// ...

/* Si vous ne souhaitez pas utiliser la fonction Transfert() pour sauvegarder le fichier,
vous devrez employer les fonctions "setTransfertOk()" et
"deleteCookieSave()" pour assurer la bonne continuité du script côté client.
Et effacer le fichier temporaire s'il est devenu inutile. */

$up->setTransfertOk();
$up->deleteCookieSave();

unlink($fichier_complet);

/* Alternativement utilisez "addStatusErreur($value)" à la place de "setTransfertOk()"
si vous souhaitez envoyer un message d'erreur */
//$up->addStatusErreur('Mon message erreur personnalisé');

/* Pour envoyer un message personnalisé qui sera concaténé au status "info.status.ok"
de la classe Javascript. */
//$up->addStatusOk('Mon message ok personnalisé');

}

/* INDISPENSABLE "exitReponseAjax()"
retourne les informations nécessaires pour la requête Ajax.*/
$up->exitReponseAjax();

Classes Php disponibles

Les classes sont situées dans le dossier "Php_Upload/Classes" et documentées dans le code source des fichiers. Elles sont chargées automatiquement dans les fichiers d'exemples de code serveur avec "spl_autoload_register".

- Les classes "UploadAjaxABCIServeur" et "UploadFormABCIServeur" héritent de la classe "UploadABCIServices".
- Les classes "UploadAjaxABCIServeur", "NettoyageTemp" et "C_PDO" utilisent la classe (trait) "ParamsDefautServeur".
- Les classes "SetMessages" et "Messages" sont utilisées un peu partout dans les scripts d'exemples et dans les classes elles-mêmes.
C_PDO
Classe de connexion BDD.
CropRedim
Classe de Crop et redimensionnement d'images (utilise la bibliothèque GD).
Messages
Classe de centralisation des messages.
NettoyageTemp
Classe de nettoyage du dossier temporaire.
ParamsDefautServeur
Trait incluant les paramétrages par défaut de la classe "UploadAjaxABCIServeur".
RedimImage
Classe de redimensionnement d'images (utilise la bibliothèque GD).
SetMessages
Classe de chargement et de sélection des messages.
UploadABCIServices
Classe de services, fonctions utilitaires communes dans un upload.
UploadAjaxABCIServeur
Classe serveur ajax (détaillée plus haut) liée à la classe javascript "UploadAjaxABCI.js".
UploadFormABCIServeur
Classe serveur pour navigateurs obsolètes (détaillée ci-dessous).
Validateur
Classe de validation des champs d'un formulaire.

Classe d'upload pour navigateurs obsolètes

La classe UploadFormABCIServeur peut être utilisée pour les navigateurs obsolètes.

Côté javascript si l'option de configuration config.browserOutdeted est définie à null, le script de la classe javascript ne sera pas exécuté pour les navigateurs obsolètes - excepté celui éventuellement défini par la fonction événementielle config.func_BrowserOutdeted() - et le formulaire sera envoyé à l'adresse définie dans l'attribut "action" du formulaire.

Cela donne une solution de secours pour les navigateurs obsolètes, sans les fonctionnalités de la classe javascript (infos temps réel, fragmentation, prévisualisations des images...) mais permettant néanmoins un upload classique 100% php.

Des exemples d'utilisation de cette classe sont donnés dans les fichiers :

Configuration de la classe "UploadFormABCIServeur"

(pour navigateurs obsolètes)
$up = new UploadFormABCIServeur($input_file,$id_form=null,$dossier_destination=null,$sort_by_name=true,$defautFatalError=true)
$input_file Nom du champ de type file.
$id_form (1) Identifiant du formulaire.
$dossier_destination (2) Dossier de destination de l'upload.
$sort_by_name (3) Trie les fichiers par leur nom. Si = false, trie les fichiers par leur taille.
$defautFatalError (4) Si = true et que les méthodes de gestions des erreurs "cathErrorServeur" ou "setModeDebug" n'ont pas été utilisées, renvoie un message si une erreur fatale survient.
Si = false ne renvoie rien dans les mêmes conditions.

Notes :
(1) Non utilisé par l'upload lui-même mais sert d'ancre de redirection pour l'affichage des résultats.

(2) Non utilisé par l'upload lui-même mais sert pour définir la propriété "destination" de l'objet contenant les informations sur le fichier. L'adresse du dossier passé en paramètre doit comporter un séparateur final, ex: $dossier = 'Destination_Upload2/';

(3) Voir le fichier "UploadAjaxABCI_Redimensions_CompNavObs.php" pour un exemple d'utilisation.
Permet dans le cas d'un traitement serveur complémentaire à l'upload (ex: redimensionnement d'images) et lors d'un upload multiple, de traiter les fichiers par ordre de taille croissante. Ainsi si une erreur fatale survient, tous les fichiers susceptibles de pouvoir être traités le seront avant l'erreur fatale qui terminera l'exécution du script. Utile dans la mesure où le traitement renverra une erreur fatale suivant le poids des fichiers, ce qui est souvent le cas.

(4) Ce message correspond à l'index 'UpAbdefautFatalErrorPhpForm' du tableau "uploadFormServeur" du fichier "Classes/Messages.php".

Méthodes de la classe "UploadFormABCIServeur"

cathErrorServeur ($array_erreur)
cf gestion des erreurs fatales du serveur. Ne pas tenir compte des lignes concernant les messages javascript (écrites dans le contexte de l'utilisation de la classe serveur "UploadAjaxABCIServeur")
setModeDebug()
cf gestion des erreurs fatales du serveur. Ne pas tenir compte des lignes concernant les messages javascript (écrites dans le contexte de l'utilisation de la classe serveur "UploadAjaxABCIServeur")
getFiles()
Retourne le tableau des fichiers. Chaque fichier à des propriétés enregistrées dans un objet détaillé ci-dessous.
deleteFiles
Détruit le tableau des fichiers.
getParam ($index)
Retourne uniquement les index "uniqid_form", "id_form" et "input_name".
A noter que lorsque l'index "uniqid_form" est passé en paramètre la fonction retourne $_POST['UpAbci_uniqidForm'], ou si non disponible retourne $_GET['UpAbci_uniqidForm'].
getPost($index)
return filter_input(INPUT_POST, $index).
addInfosServer($message)
Envoie un message dans la propriété "Infos_server" du tableau des résultats.
addErrorServer($message)
Envoie un message dans la propriété "Error_server" du tableau des résultats.
addVerifTokenFalse($deleteFile = true)
Envoie un message de requête invalide dans la propriété "Error_server" du tableau des résultats et efface (par défaut) le tableau des fichiers si $deleteFile = true.
getResult()
Récupère le tableau des résultats. Cf. contenu ci-dessous. Cette méthode efface la variable de session qui contient le tableau des résultat dès qu'elle est appelée. L'enregistrement du résultat dans une variable de session (réalisé de manière transparente par la classe) permet de rafraîchir la page avant d'annoncer les résultats pour éviter un nouvel upload en cas de rafraîchissement de la page de la part du visiteur. Et son effacement automatique permet d'annuler ces résultats pour réinitialiser le formulaire au prochain rafraîchissement de la page. Voir exemples d'utilisation dans les scripts compatibles pour navigateurs obsolètes.
reloadPage()
Recharge la page en php. A utiliser après l'upload et avant l'affichage des résultats pour éviter un nouvel upload en cas de rafraîchissement de la page. Si vous utilisez un routeur il est possible que vous soyez amené à modifier cette fonction dans la classe "UploadFormABCIServeur.php".

Méthodes héritées de la classe "UploadABCIServices"

getUniqid
returnOctets
verifExtensions
renameIdenticName
cleanFileName
fonctionnalités identiques et décrites dans la classe "UploadAjaxABCIServeur" pour ces méthodes héritées.

Contenu de l'objet spécifique à chaque fichier :

propriétécontenu
namenom du fichier
tmp_nameadresse du fichier temporaire
sizetaille du fichier
typetype du fichier
errormessage d'erreur si une erreur spécifique au fichier est intervenue
oknull par défaut (à renseigner par le script)
clean_namedisponible uniquement si aucune erreur n'est intervenue, renseigné avec le nom du fichier nettoyé soit :
cleanFileName('name')
destinationdisponible uniquement si aucune erreur n'est intervenue, destination avec le nom du fichier nettoyé soit :
$dossier_destination.cleanFileName('name')

Contenu du tableau des résultat :

propriétécontenu
FilesObjet tableau des objets spécifiques aux fichiers (cf. ci-dessus)
Error_serverErreur serveur renseignée par la classe d'upload sur dépassement des configurations serveur "post_max_size" ou "max_file_uploads" ou sur une erreur de vérification du token ou sur une erreur fatale.
A noter que l'erreur de dépassement "upload_max_filesize" est renseignée dans la propriété "error" de l'objet spécifique au fichier.
Infos_serverPropriété libre non utilisée par la classe.
Ces trois propriétés existent toujours dans le tableau des résultats. Si non renseignées, "Files" retourne un objet tableau vide, et "Error_server" et "Infos_server" valent null.

Mise en production

Tests en local

Pour faire des tests sur un serveur local il est conseillé de ne pas diminuer la valeur du paramètre config.ajaxTimeOut qui permet d'espacer l'envoi des requêtes et donc de soulager votre serveur. Evitez de mettre cette valeur à zéro.
Eviter également d'ouvrir plusieurs onglets ou fenêtres du même formulaire car vous risquer de vous trouver dans des conditions défavorables si vous tentez de télécharger le même gros fichier simultanément depuis des onglets différents.

Externalisation des scripts et des dossiers d'upload

(à l'usage des débutants)

Lors de la mise en production sur un serveur distant, supprimez les formulaires inutiles.

La plupart du temps vous souhaiterez externaliser vos formulaires par rapport au dossier Upload-Ajax-ABCI. Il vous suffira de supprimer tous les fichiers de formulaires - mais pas les dossiers - qui sont à la racine de ce répertoire pour protéger vos scripts. En effet tous les fichiers inclus dans les sous-dossiers du dossier "Upload-Ajax-ABCI" sont protégés par un token ou un .htaccess ou sont inoffensifs, donc seul l'effacement des fichiers situés à la racine du dossier "Upload-Ajax-ABCI" est nécessaire.

A/ Externalisation des formulaires

En respectant cette procédure il vous sera facile d'externaliser un formulaire, en changeant simplement les liens vers les fichiers du module d'upload, sans avoir rien d'autre à modifier (excepté éventuellement le nom des dossiers et le nom des fichiers des formulaires comme expliqué plus loin au point B).

Par exemple si l'on choisissait d'utiliser les formulaires
UploadAjaxABCI_Custom_VerifFileExist.php et UploadAjaxABCI_Inscription_Photo_Crop.php
en les plaçant au même niveau que le répertoire Upload-Ajax-ABCI (et non plus à l'intérieur).

1/ UploadAjaxABCI_Custom_VerifFileExist.php devra être modifié en remplaçant les lignes :
require 'Php_Upload/Classes/UploadABCIServices.php';
<script src="Javascript/jquery.js"></script>'
<script src="Javascript/UploadAjaxABCI.js"></script>
var destination_ajax_upload = 'Php_Upload/UploadAjaxABCI_Php_Load_Custom_VerifFileExist.php';
var destination_ajax_verif_file = 'Php_Upload/UploadAjaxABCI_VerifFileExist.php';
par :
require 'Upload-Ajax-ABCI/Php_Upload/Classes/UploadABCIServices.php';
<script src="Upload-Ajax-ABCI/Javascript/jquery.js"></script>
<script src="Upload-Ajax-ABCI/Javascript/UploadAjaxABCI.js"></script>
var destination_ajax_upload = 'Upload-Ajax-ABCI/Php_Upload/UploadAjaxABCI_Php_Load_Custom_VerifFileExist.php';
var destination_ajax_verif_file = 'Upload-Ajax-ABCI/Php_Upload/UploadAjaxABCI_VerifFileExist.php';

2/ "UploadAjaxABCI_Inscription_Photo_Crop.php" devra être modifié en remplaçant les lignes :
require 'Php_Upload/Classes/UploadABCIServices.php';
require 'Php_Upload/Classes/Messages.php';
<script src="Javascript/jquery.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script src="Javascript/jquery.imgareaselect-10-0-rc-1/jquery.imgareaselect.min.js"></script>
<link rel="stylesheet" href="Javascript/jquery.imgareaselect-10-0-rc-1/css/imgareaselect-default.css">
var destination_ajax_inscription = 'Php_Upload/UploadAjaxABCI_Inscription.php';
var destination_ajax_upload = 'Php_Upload/UploadAjaxABCI_Php_Load_Inscription.php';
par :
require 'Upload-Ajax-ABCI/Php_Upload/Classes/UploadABCIServices.php';
require 'Upload-Ajax-ABCI/Php_Upload/Classes/Messages.php';
<script src="Upload-Ajax-ABCI/Javascript/jquery.js"></script>
<script src="Upload-Ajax-ABCI/Javascript/UploadAjaxABCI.js"></script>
<script src="Upload-Ajax-ABCI/Javascript/jquery.imgareaselect-10-0-rc-1/jquery.imgareaselect.min.js"></script>
<link rel="stylesheet" href="Upload-Ajax-ABCI/Javascript/jquery.imgareaselect-10-0-rc-1/css/imgareaselect-default.css">
var destination_ajax_inscription = 'Upload-Ajax-ABCI/Php_Upload/UploadAjaxABCI_Inscription.php';
var destination_ajax_upload = 'Upload-Ajax-ABCI/Php_Upload/UploadAjaxABCI_Php_Load_Inscription.php';
ce qui aboutirait à une structure finale de ce type :

arborescence


Vous pouvez renommer le nom des fichiers des formulaires externalisés.

B/ Externalisation des dossiers d'upload

Si maintenant vous souhaitez externaliser les dossiers des fichiers d'upload, rendez-vous dans le dossier Php_Upload et les fichiers de destination Ajax qui chargent les fichiers, soit respectivement pour nos deux fichiers d'exemples :
UploadAjaxABCI_Php_Load_Custom_VerifFileExist.php
et
UploadAjaxABCI_Php_Load_Inscription.php

1/ Le dossier de destination des fichiers téléchargés avec le formulaire "Custom" sera "Custom_files", en renseignant la variable "$dossier_destination" ainsi :
(actuellement $dossier_destination = '../Destination_Upload1/')

$dossier_destination = '../../Custom_files/';

- A noter que le fichier "UploadAjaxABCI_VerifFileExist.php" (situé dans le dossier "Php_Upload") qui est nécessaire à la vérification des fichiers existants par le formulaire, comporte également la destination de l'upload. Il conviendra donc de faire la même modification pour la définition de la variable "$dossier_destination" dans ce fichier (c'est le seul exemple de formulaire dont la destination des dossiers est renseignée dans deux fichiers distincts côté serveur).


2/ Le dossier de destination des fichiers téléchargés avec le formulaire "Inscription" sera "Inscription_files", en renseignant la variable "$dossier_destination" ainsi :
(actuellement $dossier_destination = '../Destination_Upload2/')
$dossier_destination = '../../Inscription_files/';

Evidemment vous devrez créer les dossiers "Custom_files" et "Inscription_files" (et leur attribuer les droits suffisants).
Après suppression de tous les dossiers et fichiers inutiles, on aura donc la structure suivante :

arborescence


Vous pouvez renommer le nom des fichiers des formulaires externalisés.

C/ Mode "use strict" pour le code Javascript

(facilite le débugage, facultatif mais recommandé)
Chaque exemple de formulaire déclare le mode "use strict" en haut du code Javascript. Vous pouvez supprimer cette ligne si vous utiliser du code complémentaire non compatible avec ce mode.

Technique d'upload utilisée, maintenance

Upload les fichiers par fragments compilés dans un fichier temporaire quand ils dépassent une valeur paramétrable ($UpAbci_fragmentSize dans mes exemples, cf. configuration du formulaire).

L'upload terminé, le fichier temporaire est renommé avec son nom initial (éventuellement corrigé) et déplacé vers son emplacement définitif.

Cette technique totalement transparente pour l'utilisateur, permet de télécharger aussi bien des petits fichiers que des très gros en s'affranchissant des limitations serveurs "upload_max_filesize", "post_max_size", "max_file_uploads" et permet la reprise d'un téléchargement interrompu après un arrêt volontaire ou une panne interne ou serveur, en utilisant la partie sauvegardée déjà téléchargée.

Plus de détails

Nettoyage du dossier des fichiers temporaires

La classe nommée "NettoyageTemp", inclus dans le dossier "Php_Upload/Classes", contient un exemple de script pour nettoyer les fichiers abandonnés en cours d'upload dans le dossier temporaire. Penser à utiliser ce script (ou équivalent) régulièrement si besoin. Un cron peut-être une bonne solution.

Si vous limiter la possibilité d'upload des fichiers à une taille inférieure ou égale à la taille du fragment – 10 ko (1), aucune fragmentation ni sauvegarde n'est faite (excepté en cas d'utilisation de la fonction serveur Php saveAll()) et donc vous n'aurez pas besoin de nettoyer ce dossier qui restera vide. Vous obtenez dans ce cas un comportement standard (fichier temporaire effacé automatiquement à la fin du script) avec des capacités standard (le fichier ne pourra pas excéder les limitations serveur) et sans possibilité de sauvegarde intermédiaire.

(1) Vous pouvez limiter la taille des fichiers avec l'option Javascript config.fileSizeMax. Dans ce cas il est conseillé de refaire ce même contrôle côté serveur par mesure de sécurité. 10 ko sont réservés arbitrairement par le module d'upload pour les données de type texte de sorte que la taille réelle des fragments sera celle indiquée – 10 Ko.

Remarque : En complément de la limitation de la taille des fichiers côté Javascript, un moyen simple d'interdire la fragmentation des fichiers côté serveur est de fournir un nom de dossier temporaire vide ('') dans l'initialisation de la classe Php.

Notes techniques

Détails sur la sauvegarde

Le script d'upload utilise le fichier temporaire sauvegardé (si disponible) pour compléter le téléchargement, automatiquement dès la sélection du même fichier, ou après demande de confirmation. La durée de disponibilité de la sauvegarde dépend de la durée de vie du cookie envoyé par le script Php d'upload.

Le nom du cookie qui contient les informations de sauvegarde associées au fichier est composé de l'identifiant du formulaire, du nom du champ de type file (1), ainsi que du nom et de la taille du fichier. Cela est suffisant dans la mesure où il est extrêmement rare qu'on possède sur son ordinateur deux fichiers qui aient exactement le même nom et la même taille tout en étant différents, et que l'on télécharge ensuite le second à la suite de l'échec du téléchargement du premier. Pour cette raison la reprise d'upload est automatique par défaut mais on peut configurer le script pour qu'il demande une confirmation de reprise avec l'option Javascript config.recoveryBackupConfirm.

Les informations de sauvegarde sont enregistrées dans un cookie, on ne peut donc récupérer un fichier partiellement téléchargé que depuis le même navigateur et le même formulaire (1) qui a envoyé la partie sauvegardée. Pour les reprises d'upload, faire attention de pouvoir récupérer les cookies envoyés par le script Php. Un cookie envoyé sur http://monsite.net ne pourra pas être récupéré depuis http://www.monsite.net, et inversement. En cas de problème lors du téléchargement, un visiteur qui s'est connecté depuis la première adresse ne pourra donc pas récupérer la partie sauvegardée s'il se connecte depuis la seconde adresse lors de sa visite suivante. Pour éviter ce problème, on peut définir une adresse unique par réécriture d'url dans un .haccess.

(1) Comportement modifiable avec l'option Javascript config.BackupFormDependency détaillée ci-dessous.

Conditions de reprise d'upload

L'option Javascript config.BackupFormDependency = true lie les possibilités de reprise d'upload des fichiers à l'identifiant (classe ou id) du formulaire ainsi qu'au nom du champ de type file.
Si = false, ces éléments ne sont pas utilisés pour créer le nom du cookie de sauvegarde. Cela permet de récupérer l'éventuelle sauvegarde d'un fichier depuis différents formulaires, mais induit un problème dans le cas particulier où l'on télécharge simultanément des fichiers identiques depuis des formulaires différents : le second upload va retrouver la sauvegarde en cours du premier et le fichier final sera corrompu. Le script renverra alors un message d'erreur en fin d'upload "Fichier temporaire non valide".
Même chose si config.BackupFormDependency = true et que l'on ouvre le même formulaire dans différents onglets pour télécharger simultanément le même fichier.
Bien entendu ces remarques ne valent que pour les gros fichiers qui dépassent la taille d'un fragment (défini par $UpAbci_fragmentSize dans les formulaires donnés en exemples). Les fichiers plus petits ne nécessitant pas de sauvegarde temporaire ni donc de cookie.

Taille maximale des fichiers

Il n'y a pas de limite à la taille des fichiers, exceptées celles définies par vous-même. J'ai testé avec succès des fichiers de plus de 9 Go en local. Sur serveurs mutualisés distants je me suis limité à des tests de 2,5 Go (car faut faire preuve de patience...).
La vitesse dépend de votre débit ascendant (aux alentours d'1Mb actuellement avec adsl classique) mais aussi de la vitesse d'upload qui peut être limitée sur le serveur distant.
Par ailleurs certains serveurs mutualisés renvoient plus ou moins souvent une erreur 500 au bout d'un certain temps. Cela permet toutefois d'envoyer dans les 300 à 500 Mo en une seule passe que l'on pourra éventuellement compléter en réinitialisant le téléchargement. Sur ces mêmes serveurs j'ai néanmoins pu télécharger des fichiers de 1,5 Go en une seule passe, c'est donc très variable et dépend très probablement de l'activité globale du serveur.

Interactions Javascript/Serveur

A lire plus particulièrement si vous souhaitez utiliser une autre technologie que PHP côté serveur.
Javascript vers Serveur
Se référer au paragraphe récupération des paramètres prédéfinis de la requête ajax.
Les variables "UpAbci_blobSlice" et "UpAbci_fileEnd" donnent les indications de traitement au serveur :

a/ Si le fichier est en un seul fragment (UpAbci_blobSlice != 1), le transfère utilise le dossier temporaire du système et la procédure habituelle.

b/ Si le fichier est en plusieurs morceaux (UpAbci_blobSlice == 1), le fragment de fichier est enregistré dans $dossier_temporaire. Un cookie est envoyé par Php qui indique le nom unique et sécurisé du fichier temporaire et la taille uploadée. Ce principe permet de reprendre le téléchargement d'un fichier partiellement enregistré après une interruption totale du système. Ensuite tant que la variable Javascript "UpAbci_fileEnd" est différente de 1 le fichier temporaire est complété, puis exploité quand elle vaut 1.
Serveur vers Javascript

La classe Javascript recherche 6 variables en retour serveur dans un tableau JSON :

propriétécontenu
upabci_resultatavec comme valeurs 'continu' ou 'upload_ok' à usage interne suivant que le fichier est terminé ou non.
upabci_okcontenant des messages personnalisés concaténés au paramètre "info.status.ok" de la classe Javascript et envoyé dans le bloc html ayant la classe "UpAbci_status".
upabci_erreurcontenant des messages d'erreurs personnalisés concaténés au paramètre "info.status.erreur" de la classe Javascript et envoyé dans le bloc html ayant la classe "UpAbci_status".
upabci_infos_serverun message texte ou html qui sera inséré dans le retour d'information général du formulaire ayant la classe "UpAbci_infosServer".
upabci_mixte_serverun contenu texte, html ou un tableau de données qui pourra être récupéré en troisième paramètre des fonctions Javascript événementielles "config.func_FileEndEach" et "config.func_FormEnd". N'envoie rien dans le html. Vous exploiterez ces données comme bon vous semble.
upabci_stop_formavec les valeurs 0 ou 1. Stoppe la soumission du formulaire en permettant néanmoins d'envoyer l'éventuelle requête de confirmation de fin de formulaire (quand "config.queryFormEnd=true) si "upabci_stop_form = 1".
Suivant qu'un cookie existe ou non, la classe Javascript informera ou non de l'existence d'une sauvegarde. Si le fichier est interrompu en cours d'upload, cette sauvegarde sera exploitée à la prochaine soumission du fichier, avec ou sans demande de confirmation suivant la valeur de l'option Javascript config.recoveryBackupConfirm.

Consultez le fichier Javascript "UploadAjaxABCI_DEV.js" en faisant une recherche sur ".done" pour avoir plus de détails sur l'exploitation du retour Ajax.

Debug

1/ En cas de problème cliquez sur le lien suivant Test_config.php afin de contrôler les autorisations requises pour lire et écrire dans les dossiers de destination d'upload.
- Toutes les lignes doivent retourner "status ok", sinon attribuer des droits d'accès suffisants aux dossiers avec votre logiciel FTP.
- Les valeurs "post_max_size" et "upload_max_filesize" du serveur sont indiquées pour information. La plus petite de ces valeurs détermine la valeur maximale des fragments.
- Si vous utilisez un serveur de type FAI - exemple sites perso chez Free - consultez le paragraphe 4.

2/ Une fois le contrôle précédent réussi, si un problème persiste la valeur critique à modifier est la valeur des fragments, soit la variable Php "$UpAbci_fragmentSize" dans les exemples de formulaires.

En effet, si tous les fichiers incluent une vérification des configurations "post_max_size" et "upload_max_filesize" du serveur pour contrôler la valeur maximale des fragments, d'autres paramètres non accessibles depuis Php peuvent intervenir :
- par exemple certains serveurs "nginx" ont (ou avaient) par défaut une configuration serveur "client_max_body_size" de 1Mo qui va également limiter la taille de l'upload. Dans ce cas particulier, l'upload sera réinitialisé pour chaque fragment envoyé et le script renverra un message d'erreur plus ou moins documenté au bout d'un certain temps. A noter que l'administrateur serveur devrait pouvoir augmenter la valeur de cette configuration sans problème (c'est plus souvent un oubli qu'autre chose).

En cas de problème vous pouvez définir la valeur des fragments à 1Mo, puis augmenter par pas de 1 Mega.

Lors des tests si vous obtenez systématiquement le message d'erreur :

"Connexion non valide ou perdue. Rafraîchissez la page et recharger votre fichier, si celui-ci dispose d'une sauvegarde automatique elle sera utilisée."

Deux erreurs sont possibles :
- Les sessions ne fonctionnent pas (très rare).
- Plus probablement la taille des fragments est supérieure à ce que peut supporter le serveur (1). Appliquez alors une modification de la taille des fragments comme indiqué ci-dessus ou optimisez la configuration de votre serveur.

(1) Si la valeur de "post_max_size" est dépassée alors les super globales $_POST et $_FILES sont nulles. Le jeton de contrôle du formulaire sera invalide puisqu'il transite dans une variable $_POST. D'où le message d'erreur renvoyé par le script Php d'upload. Ce message sera pertinent en production car une fois bien configuré le principal problème possible constaté est une perte de connexion qui peut intervenir après plusieurs heures d'upload en continu sur un serveur mutualisé d'entrée de gamme (probablement une limitation pour économiser des ressources serveur).

3/ Si vous obtenez le message :

"Fichier temporaire non valide."

Il est probable que vous ayez essayé de télécharger simultanément le même fichier depuis le même formulaire dans des onglets différents. Voir la note Conditions de reprise d'upload pour plus d'explications.

4/ Serveurs sites perso des fournisseurs d'accès internet, exemple avec Free :
- Contrairement aux serveurs mutualisés des hébergeurs professionnels (ovh, gandi...) les hébergeurs gratuits ont souvent des limitations sur le traitement des fichiers qui vont au delà des configurations "post_max_size" et "upload_max_filesize". Par exemple toutes les fonctions de traitement sur les fichiers (file_get_contents, fopen...) sont limitées à 2Mo chez Free (fin 2016). De sorte que même si techniquement la classe d'upload javascript pourra fragmenter les fichiers à une valeur inférieure, le code php ne pourra pas compiler et reconstruire les fichiers s'ils dépassent cette limite.

Notez que cette limitation sur la taille des fichiers est normalement la seule que vous aurez sur ce type de serveur. Toutes les autres fonctionnalités sont préservées, notamment : informations en temps réel, redimensionnements, recadrage, et pas de limitation concernant le nombre de fichiers.

Exemple de configuration sur serveur Free - nécessite d'utiliser au minimum la version php 5.6 disponible depuis l'été 2016 :

Code php qui alimente le formulaire:
session_start();
// La ligne ci-dessous est inutile à partir de php 5.6 car utf8 est la configuration par défaut
// header('Content-type: text/html; charset=UTF-8');

require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();
$UpAbci_fragmentSize = $up->returnOctets('3M'); /* limité à 2Mo chez Free. On met 3Mo pour ne pas déclencher la fragmentation des fichiers dans les cas limites (avoisinant 2.0mo) et on limitera la taille des fichiers à 1.99 dans la configuration javascript.*/

$UpAbci_uniqidForm = $up->getUniqid();

// Jeton de formulaire
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;

Configuration de la classe javascript :
Ajoutez une ligne pour limiter la taille des fichiers légèrement en dessous de 2Mo
Up.config.fileSizeMax = '1.99M';
Pour le reste des configurations, options et possibilités, vous pouvez prendre modèle sur tous les exemples fournis.

Forum de discussion, liens

Lien de téléchargement du module d'upload

Forum de discussion

imgareaselect Plugin jQuery de Crop - Recadrage

fileEXIF Plugin jQuery pour lire les informations EXIF d'une photo "jpg" ou "tiff" provenant d'un appareil photo numérique.

Tutoriel


Pour information, ce tutoriel est également disponible en ligne ici.

La configuration de l'affichage des informations et du comportement du formulaire est réalisée directement dans le code HTML avec des classes prédéfinies et des styles événementiels. Ce module d'upload Ajax-jQuery peut donc être utilisé par des débutants sans connaissances en JavaScript tout en bénéficiant des fonctionnalités intégrées.

Pour aller plus loin, des fonctions JavaScript événementielles (callback) sont disponibles pour permettre d'exécuter du code JavaScript personnalisé en fonction des différentes étapes de traitement des fichiers.

Parallèlement à la lecture de ce tutoriel, vous pouvez consulter le mode d'emploi pour des informations plus exhaustives. Dans un premier temps, je conseille cependant, notamment pour les débutants, de se référer principalement à l'exemple ci-dessous pour éviter de se sentir submergé par toutes les options disponibles. Vous constaterez que l'on peut configurer un upload disposant de nombreuses fonctionnalités avec un minimum de paramétrages faciles à mettre en place.

Cet exemple est basé sur le formulaire UploadAjaxABCI_Basique.php et sur son script serveur UploadAjaxABCI_Php_Load_Basique.php fournis dans le dossier en téléchargement.

Configuration du formulaire

Le formulaire doit posséder un identifiant html, "id" ou "class", qui sera passé en premier paramètre lors de l'initialisation de la classe JavaScript. Alternativement ce paramètre pourra être un objet jQuery.

Affichage des informations des fichiers

L'affichage des informations spécifiques à chaque fichier se fait à l'intérieur d'un bloc HTML (div, p...) auquel on attribuera la classe UpAbci_infosFile. Notez que ce bloc sera dupliqué en cas d'upload multiple, en conséquence n'utilisez pas d'identifiant unique de type "id" pour cet élément et pour ses éléments contenus.

Pour des raisons pratiques et techniques, ce bloc devra être inclus dans un conteneur dont on passera l'identifiant comme troisième paramètre dans l'initialisation de la classe JavaScript.

A savoir que si ce bloc est nécessaire pour l'affichage des informations spécifiques à chaque fichier, il est cependant facultatif pour le fonctionnement de l'upload, on peut donc réaliser un formulaire minimaliste, mais néanmoins fonctionnel.

Pour afficher les informations spécifiques à chaque fichier, il suffit de définir des éléments HTML en appliquant des classes réservées à cet effet. Je choisis ici d'utiliser des "span" pour un affichage en ligne, par exemple :
<span class="UpAbci_imgPreview"></span>
affichera une vignette de prévisualisation si le fichier est une image, sinon rien.
<span class="UpAbci_name"></span>
affichera le nom du fichier.
<progress class="UpAbci_progressionG"></progress>
affichera une barre de progression graphique de l'upload.
<span class="UpAbci_status">en attente</span>
affichera le statut du fichier: "en cours", "ok", "erreur" ou "arrêt" en fonction de l'état et du résultat du téléchargement. Ces libellés sont paramétrables dans les options de configuration de la classe JavaScript. Notez que l'on peut mettre une valeur par défaut dans l'élément d'information, ici j'ai mis "en attente", elle sera remplacée automatiquement par l'information adéquate durant le téléchargement du fichier.

Remarque : l'affichage de la progression graphique nécessite l'emploi de la balise progress. C'est la seule information qui nécessite l'utilisation d'une balise spécifique.

Liste des classes prédéfinies. Des informations supplémentaires peuvent être retournées en utilisant les fonctions JavaScript événementielles cf mode d'emploi

A ce stade, nous avons le formulaire suivant :
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" />
<input type="submit" value="Envoyer" />

<!-- Bloc conteneur du retour d'informations -->
<div id="reponse_upload">
<!--Retour des informations spécifiques aux fichiers -->
<div class="UpAbci_infosFile">
<span class="UpAbci_imgPreview"></span>
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status">en attente</span>
</div>
</div>
</form>
Ce code est suffisant pour afficher quatre informations et réaliser l'upload d'un fichier sans limites de taille sur des serveur mutualisés type OVH, Gandi etc. (pour autant on peut bien entendu limiter la taille maximale des fichiers).

Par ailleurs les gros fichiers disposeront d'une sauvegarde automatique permettant une reprise de téléchargement en cas de problème ou d'arrêt volontaire durant l'upload.

Il suffira d'ajouter l'attribut multiple="multiple" dans le champ de type file pour permettre l'upload multiple.

Utilisation des styles événementiels

Nous allons maintenant modifier le comportement du formulaire précédemment créé, avec des styles événementiels.

La barre de progression s'affichera en attente de sélection de fichiers. On peut remédier à ce problème en cachant le bloc d'informations et en l'affichant uniquement si des fichiers sont sélectionnés, en utilisant le style css événementiel data-upabcicss-select-file qui sera déclenché dès la sélection de fichiers:
<div class="UpAbci_infosFile" style="display:none" data-upabcicss-select-file="display:block;">
Si je souhaite maintenant que le statut du fichier s'affiche en vert et en gras uniquement lorsqu'il est correctement téléchargé je peux utiliser le style événementiel data-upabcicss-result-ok :
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
Nous avons créé un formulaire dynamique possédant des fonctionnalités avancées sans besoin de programmer une seule ligne de code JavaScript.
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" />
<input type="submit" value="Envoyer" />

<!-- Bloc conteneur du retour d'informations -->
<div id="reponse_upload">
<!--Retour des informations spécifiques aux fichiers -->
<div class="UpAbci_infosFile" style="display:none" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span>
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
</div>
</div>
</form>
Liste des styles événementiels

Champs complémentaires utilisés pour l'upload

Le code du formulaire précédemment défini est fonctionnel en l'état. Cependant, la classe JavaScript recherchera deux champs input nommés UpAbci_uniqidForm et UpAbci_fragmentSize pour récupérer et renvoyer ces données complémentaires issues du serveur.

Le premier permet de définir un jeton de sécurité qui sera contrôlé côté serveur lors de l'upload, et le second sert à indiquer la taille des fragments qui déterminera la fréquence des sauvegardes automatiques.

Si ces champs sont absents, la classe utilisera des valeurs par défaut. On peut aussi alternativement définir ces valeurs dans les options de configuration de la classe JavaScript.

Pour une meilleure sécurité des scripts, les exemples de formulaires fournis dans le dossier en téléchargement définissent une variable de session en php qui servira de token. Typiquement :
<?php
session_start();
header('Content-type: text/html; charset=UTF-8');// Inutile avec php >= 5.6

// Charge la classe de services php pour les fonctions "returnOctets" et "getUniqid"
require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();

// On choisi ici des fragments de 2Mo pour l'exemple (à augmenter si possible pour les gros fichiers, sinon cela générerait beaucoup de trafic serveur)
$UpAbci_fragmentSize = $up->returnOctets('2M');

// Variable aléatoire unique utilisée pour la définition du token (jeton de sécurité) enregistré dans une variable de session
$UpAbci_uniqidForm = $up->getUniqid();

// Enregistrement de la variable de session qui sera comparée lors de l'upload
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
?>
Note : Le code des exemples fournis définit une taille de 8Mo pour les fragments et vérifie que cette valeur n'est pas supérieure aux limites serveur (utile uniquement si vous ne les connaissez pas).

Nous retrouvons donc le code html du fichier d'exemple : UploadAjaxABCI_Basique.php, avec ces deux champs complémentaires. J'ai ajouté également l'attribut multiple="multiple" dans le champ de type file pour permettre l'upload multiple et un lien pour stopper l'envoi des fichiers avec la classe UpAbci_stop dans le dernier "span" :
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" multiple="multiple" />
<input type="hidden" value="<?=$UpAbci_uniqidForm?>" name="UpAbci_uniqidForm" />
<input type="hidden" value="<?=$UpAbci_fragmentSize?>" name="UpAbci_fragmentSize" />
<input type="submit" value="Envoyer" />

<!-- Bloc conteneur du retour d'informations -->
<div id="reponse_upload">
<!--Retour des informations spécifiques aux fichiers -->
<div class="UpAbci_infosFile" style="display:none" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span>
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
<span class="UpAbci_stop" style="color:red">stop</span>
</div>
</div>
</form>

Champs supplémentaires dans le formulaire

Vous pouvez ajouter d'autres champs dans le formulaire, ils seront transmis côté serveur. La notation tableau est également acceptée. Utilisez la fonction php urldecode pour récupérer leur valeur.

Pour ajouter des champs spécifiques à chaque fichier - par exemple pour définir un champ légende pour chaque fichier lors d'un upload multiple – consultez les exemples de Crop dans liste des fichiers disponibles.

Configuration de la classe JavaScript

Il est conseillé de mettre le code JavaScript juste avant ou juste après la fermeture de la balise "</body>" du formulaire.

La classe JavaScript d'upload est inclue dans le fichier UploadAjaxABCI.js. Elle utilise jQuery que l'on charge en premier.

L'initialisation de la classe JavaScript requiert respectivement l'identifiant du formulaire, la destination de la requête ajax, et l'identifiant du bloc conteneur des informations des fichiers (ce troisième paramètre est facultatif pour l'upload mais indispensable pour une information détaillée sur les fichiers).

Vous pouvez ensuite ajouter des options de configuration pour définir par exemple les extensions de fichiers autorisées, la taille des vignettes de prévisualisation, la taille maximale des fichiers etc. De nombreuses options sont disponibles ainsi que des fonctions JavaScript événementielles. On termine en utilisant la fonction Start().
<script src="Javascript/jquery.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script>
// Destination de la requête ajax d'upload
var destination_ajax = 'Php_Upload/UploadAjaxABCI_Php_Load_Basique.php';

// Initialisation de la classe JavaScript (identifiant formulaire, destination ajax, identifiant réponse)
var up = new UploadAjaxABCI('#form_base',destination_ajax,'#reponse_upload');

/* configuration optionnelle. Par exemple pour limiter les fichiers à une taille de 100Mo :
up.config.fileSizeMax = '100 Mo';
*/

// Démarrage de la fonction, DOM chargé
$(function(){up.Start()});
</script>

Récapitulatif de la page complète du formulaire

<?php
session_start();
require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();
$UpAbci_fragmentSize = $up->returnOctets('2M');
$UpAbci_uniqidForm = $up->getUniqid();
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Basique Upload Ajax ABCIWEB</title>
</head>
<body>
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" multiple="multiple" />
<input type="hidden" value="<?=$UpAbci_fragmentSize?>" name="UpAbci_fragmentSize" />
<input type="hidden" value="<?=$UpAbci_uniqidForm?>" name="UpAbci_uniqidForm" />
<input type="submit" value="Envoyer" />

<div id="reponse_upload">
<div class="UpAbci_infosFile" style="display:none;" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span>
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
<span class="UpAbci_stop" style="color:red">stop</span>
</div>
</div>
</form>
</body>
<script src="Javascript/jquery.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script>
var destination_ajax = 'Php_Upload/UploadAjaxABCI_Php_Load_Basique.php';
var up = new UploadAjaxABCI('#form_base',destination_ajax,'#reponse_upload');
$(function(){up.Start()});
</script>
</html>
Pour une mise en page plus aboutie, utilisez le fichier UploadAjaxABCI_Basique.php fourni dans le module d'upload.

Configuration du script côté serveur

Il s'agit ici du fichier d'exemple UploadAjaxABCI_Php_Load_Basique.php qui est le fichier de destination Ajax du formulaire précédent. Une classe Php d'upload UploadAjaxABCIServeur et de nombreuses classes annexes sont disponibles pour faciliter le code serveur. Elles sont détaillées dans le mode d'emploi et dans les fichiers d'exemples fournis.

Pour un upload sans traitement complémentaire, 10 lignes génériques suffisent :
<?php
// Vous devez vérifier l'existence du dossier ou changer cette adresse
$dossier_destination = '../Destination_Upload1/';

session_start();
header('Content-type: text/html; charset=UTF-8');// Inutile avec php >= 5.6

// Charge les classes php avec spl_autoload_register
spl_autoload_register(function ($class) {require 'Classes/' . $class . '.php ';});

// Initialisation de la classe d'upload php (dossier de destination)
$up = new UploadAjaxABCIServeur($dossier_destination);

// retourne l 'identifiant de formulaire pour la vérification ci-dessous
$uniqid_form = $up->getParam("uniqid_form");

// Vérification du jeton de sécurité
if(!(isset($uniqid_form,$_SESSION['UploadAjaxABCI'][$uniqid_form]['token'])))
{
//Sort du script en envoyant un message si la vérification échoue
$up->exitStatusErreur('Jeton de sécurité non valide');
}

// Le processus d'upload est dissocié de celui du transfert, pour permettre de traiter le fichier complet (par exemple pour faire des redimensionnements d'images en php, etc.) avant de le déplacer vers son emplacement définitif
$up->Upload();

$up->Transfert();

// INDISPENSABLE en fin de script, "exitReponseAjax()" retourne les informations nécessaires pour la requête ajax.
$up->exitReponseAjax();
?>
A noter que dans le fichier d'exemple fourni dans le dossier, le message "Jeton de sécurité non valide" est remplacé par un message plus complet avec :
$up->exitStatusErreur(SetMessages::setMess('UpAbVerifToken'));
En effet une classe SetMessages permet d'utiliser des messages définis dans une classe Messages. C'est pratique si vous avez plusieurs formulaires à traiter ou du code complexe faisant intervenir plusieurs fichiers ou une traduction à proposer suivant la langue du visiteur.

Fonctions JavaScript événementielles

Tout comme les styles événementiels permettent d'exécuter des styles CSS en fonction du traitement des fichiers, les fonctions JavaScript événementielles permettent d'exécuter du code JavaScript en fonction du traitement des fichiers. De nombreux exemples d'utilisation sont donnés dans le code source des fichiers de démonstration et la liste des fonctions disponibles est détaillée ici.

Ci-dessous, un exemple pour afficher les informations Exif des fichiers jpg/jpeg et tiff qui sont enregistrées dans les images des appareils photo numériques. J'utilise ici la fonction événementielle config.func_FileSelectEach qui sera exécutée à la sélection de chaque fichier en exploitant les paramètres disponibles dans la fonction.
config.func_FileSelectEach = function(e,obj) {}
Le paramètre e retourne l'objet event et le paramètre obj retourne un objet contenant de nombreuses propriétés. Notamment la propriété fichier renvoie le fichier en cours et la propriété infos_html renvoie le contexte html spécifique au fichier.
La propriété fichier sera utilisée pour instancier le plugin jQuery fileExif et la propriété infos_html sera utilisée pour afficher certaines informations Exif dans le formulaire.
up.config.func_FileSelectEach = function(e,obj)
{
// Fonction de callback appelée par le plugin "fileExif" initialisé plus bas
var exifCallback = function(exifObject)
{
// Si les informations EXIF sont renseignées
if(exifObject !== false)
{
// Décommenter la ligne ci-dessous pour voir toutes les informations disponibles (elles sont nombreuses)
// console.log(exifObject);

// Affichage des informations voulues dans l'élément html ayant la classe "photo_exif"
obj.infos_html.find('.photo_exif').html("marque : "+exifObject.Make+"<br>modèle : "+exifObject.Model+"<br>programme d'exposition : "+exifObject.ExposureProgram+"<br>date : "+exifObject.DateTime);
}
}

// On récupère le fichier avec la propriété "fichier" de l'objet pour initialiser le plugin "fileExif"
$.fileExif(obj.fichier,exifCallback);
}
J'affiche les informations Exif dans un élément HTML ayant la classe photo_exif que j'ajouterai donc dans le formulaire récapitulatif ci-dessous.

Concernant la configuration JavaScript, j'utiliserai pour exemple l'option config.filesExtensions pour limiter l'upload à des fichiers photo (cette limitation n'est pas indispensable au fonctionnement du script).

La page complète du formulaire est donc maintenant :
<?php
session_start();
require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();
$UpAbci_fragmentSize = $up->returnOctets('2M');
$UpAbci_uniqidForm = $up->getUniqid();
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Basique Upload Ajax ABCIWEB</title>
</head>
<body>
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" multiple="multiple" />
<input type="hidden" value="<?=$UpAbci_fragmentSize?>" name="UpAbci_fragmentSize" />
<input type="hidden" value="<?=$UpAbci_uniqidForm?>" name="UpAbci_uniqidForm" />
<input type="submit" value="Envoyer" />

<div id="reponse_upload">
<div class="UpAbci_infosFile" style="display:none;" data-upabcicss-select-file="display:block;">
<p>
<span class="UpAbci_imgPreview" style="float:left"></span>
<span class="photo_exif"></span>
</p>
<p style="clear:both">
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
<span class="UpAbci_stop" style="color:red">stop</span>
</p>
</div>
</div>
</form>
</body>
<script src="Javascript/jquery.js"></script>
<!-- charge le plugin "fileExif" -->
<script src="Javascript/jquery.exif.min.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script>
var destination_ajax = 'Php_Upload/UploadAjaxABCI_Php_Load_Basique.php';
var up = new UploadAjaxABCI('#form_base',destination_ajax,'#reponse_upload');

// Extensions autorisées
up.config.filesExtensions = ['jpg','jpeg','png','gif','tiff'];

// Initialisation du plugin "fileExif" et affichage d'informations dans le html
up.config.func_FileSelectEach = function(e,obj)
{
// Fonction de callback appelée par le plugin "fileExif" initialisé plus bas
var exifCallback = function(exifObject)
{
// Si les informations EXIF sont renseignées
if(exifObject !== false)
{
// Affichage des informations dans l'élément html ayant la classe "photo_exif"
obj.infos_html.find('.photo_exif').html("marque : "+exifObject.Make+"<br>modèle : "+exifObject.Model+"<br>programme d'exposition : "+exifObject.ExposureProgram+"<br>date : "+exifObject.DateTime);
}
}

// On récupère le fichier avec la propriété "fichier" de l'objet pour initialiser le plugin "fileExif"
$.fileExif(obj.fichier,exifCallback);
}

$(function(){up.Start()});
</script>
</html>
Notes :
- Le fichier d'exemple UploadAjaxABCI_Redimensions_Exif.php retourne ces mêmes informations Exif et montre comment les transmettre au serveur en utilisant la propriété libre join_file des objets JavaScript qui permet d'envoyer des informations additionnelles spécifiques à chaque fichier vers le serveur.

- Les informations Exif sont uniquement disponibles pour les photos issues des appareils photos numériques. Elles ne seront donc pas disponibles pour les fichiers "png", "gif" ni pour les fichiers "jpeg" et "jpg" qui auraient été retravaillés puis enregistrés avec un logiciel photo.

Fonctions JavaScript événementielles (suite)

Ci-dessous un second exemple, toujours basé sur le code du fichier UploadAjaxABCI_Basique.php, pour faire afficher la vitesse de l'upload.

Je rajoute un élément html ayant une classe vitesse pour afficher la vitesse de transfert à l'intérieur du bloc d'information spécifique à chaque fichier défini avec la classe UpAbci_infosFile :
<div class="UpAbci_infosFile" style="display:none;margin-top:1em;" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span><!-- vignette de prévisualisation (si le fichier est une image) -->
<span class="UpAbci_name"></span><!-- nom du fichier -->
<progress class="UpAbci_progressionG"></progress> <!-- progression graphique -->
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span><!-- pour informer du statut "en cours", "ok", "erreur" ou "arrêt" en fonction de l'état du téléchargement. La mention "en attente" est écrite par défaut et sera remplacée par l'information adéquate durant le téléchargement du fichier. -->
<span class="vitesse"></span><!-- vitesse de transfert -->

<span class="UpAbci_stop" style="color:red;cursor:pointer;float:right" data-upabcicss-result="display:none">stop</span>
</div>
Côté javascript j'utilise la fonction javascript événementielle config.func_FileInProgressEach qui est appelée lors de la progression des fichiers (à une fréquence définie par l'option de configuration javascript "config.infosRefresh" soit actuellement chaque seconde). J'utilise le paramètre obj de la fonction pour récupérer les informations nécessaires et faire afficher la vitesse de l'upload.

J'ai préalablement créé une fonction BitFormate qui permet de formater le résultat en Kb/s, Mb/s, Gb/s ...

Le reste est documenté dans le code :
var BitFormate = function (Bits)
{
var Type = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"];
var Index = 0;
while(Bits >= 1000)
{
Bits /= 1000;
Index++;
}
// J'arrondi à 1 chiffre après la virgule pour '', 'K' et 'M', et 3 chiffres après la virgule pour les unités supérieures
Bits = Type[Index] == 'M' || Type[Index] == 'K' || Type[Index] == '' ? Bits.toFixed(1) : Bits.toFixed(3);
var unite = 'b/s';
return(Bits+''+Type[Index]+''+unite);
}

up.config.func_FileInProgressEach = function(obj)
{
// Utilisez console.log(obj) pour visualiser les propriétés de l'objet dans la console javascript

// La propriété "qte_upload" inclut initialement la quantité sauvegardée "qte_save_ini" en cas de reprise d'upload si on a précédemment stoppé l'upload du fichier en cours. Je retire donc cette valeur et je multiplie le résultat (qui est en octet) par huit pour avoir des bits qui sont l'unité de transfert des données.
var bit_upload = (obj.qte_upload - obj.qte_save_ini) * 8;

// la propriété "time_end" est déjà formatée en secondes, par contre "time_start" est en millisecondes.
var time_upload = obj.time_end - obj.time_start/1000;

// Cela ne devrait pas arriver mais je vérifie par sécurité que time_upload soit supérieur à 0 pour éventuellement éviter une vilaine division par 0.
if(typeof time_upload === "number" && time_upload > 0)
{
// La propriété "infos_html" de l'objet passé en paramètre à la fonction événementielle correspond à l'objet html ayant la classe "UpAbci_infosFile". Je fais afficher la vitesse formatée dans l'élément ayant la classe "vitesse"
obj.infos_html.find(".vitesse").html(BitFormate(bit_upload/time_upload));
}
}
Récapitulatif de la page :
<?php
session_start();
require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();
$UpAbci_fragmentSize = $up->returnOctets('2M');
$UpAbci_uniqidForm = $up->getUniqid();
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Basique Upload Ajax ABCIWEB</title>
</head>
<body>
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" multiple="multiple" />
<input type="hidden" value="<?=$UpAbci_fragmentSize?>" name="UpAbci_fragmentSize" />
<input type="hidden" value="<?=$UpAbci_uniqidForm?>" name="UpAbci_uniqidForm" />
<input type="submit" value="Envoyer" />

<div id="reponse_upload">
<div class="UpAbci_infosFile" style="display:none;margin-top:1em;" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span><!-- vignette de prévisualisation (si le fichier est une image) -->
<span class="UpAbci_name"></span><!-- nom du fichier -->
<progress class="UpAbci_progressionG"></progress> <!-- progression graphique -->
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span><!-- pour informer du statut "en cours", "ok", "erreur" ou "arrêt" en fonction de l'état du téléchargement. La mention "en attente" est écrite par défaut et sera remplacée par l'information adéquate durant le téléchargement du fichier. -->
<span class="vitesse"></span><!-- vitesse de transfert -->

<span class="UpAbci_stop" style="color:red;cursor:pointer;float:right" data-upabcicss-result="display:none">stop</span>
</div>
</div>
</form>
</body>
<script src="Javascript/jquery.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script>
var destination_ajax = 'Php_Upload/UploadAjaxABCI_Php_Load_Basique.php';
var up = new UploadAjaxABCI('#form_base',destination_ajax,'#reponse_upload');
var BitFormate = function (Bits)
{
var Type = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"];
var Index = 0;
while(Bits >= 1000)
{
Bits /= 1000;
Index++;
}
// J'arrondi à 1 chiffre après la virgule pour '', 'K' et 'M', et 3 chiffres après la virgule pour les unités supérieures
Bits = Type[Index] == 'M' || Type[Index] == 'K' || Type[Index] == '' ? Bits.toFixed(1) : Bits.toFixed(3);
var unite = 'b/s';
return(Bits+''+Type[Index]+''+unite);
}

up.config.func_FileInProgressEach = function(obj)
{
// Utilisez console.log(obj) pour visualiser les propriétés de l'objet dans la console javascript

// La propriété "qte_upload" inclut initialement la quantité sauvegardée "qte_save_ini" en cas de reprise d'upload si on a précédemment stoppé l'upload du fichier en cours. Je retire donc cette valeur et je multiplie le résultat (qui est en octet) par huit pour avoir des bits qui sont l'unité de transfert des données.
var bit_upload = (obj.qte_upload - obj.qte_save_ini) * 8;

// la propriété "time_end" est déjà formatée en secondes, par contre "time_start" est en millisecondes.
var time_upload = obj.time_end - obj.time_start/1000;

// Cela ne devrait pas arriver mais je vérifie par sécurité que time_upload soit supérieur à 0 pour éventuellement éviter une vilaine division par 0.
if(typeof time_upload === "number" && time_upload > 0)
{
// La propriété "infos_html" de l'objet passé en paramètre à la fonction événementielle correspond à l'objet html ayant la classe "UpAbci_infosFile". Je fais afficher la vitesse formatée dans l'élément ayant la classe "vitesse"
obj.infos_html.find(".vitesse").html(BitFormate(bit_upload/time_upload));
}
}

$(function(){up.Start()});
</script>
</html>

Conclusion

Les exemples ci-dessus montrent que ce module d'upload possède de nombreuses fonctionnalités tout en étant accessible aux débutants avec les classes HTML prédéfinies pour accueillir les informations en temps réel et les styles événementiels pour gérer leur affichage.

Pour les utilisateurs ayant des connaissances en JavaScript, les fonctions événementielles permettent d'aller plus loin et d'interfacer le script avec des plugins jQuery externes ou d'ajouter du code personnalisé.

Idéalement, cet outil est à utiliser avec PHP côté serveur puisque les classes PHP fournies permettent de proposer des exemples directement fonctionnels. Ainsi il vous suffit de poser le dossier préconfiguré sur le serveur pour faire les premiers tests.

Pour d'autres fonctionnalités, recadrage (crop), redimensions d'images, validation de formulaire, etc. consultez les autres exemples fournis et les commentaires dans le code source de ces fichiers.