# Upload de fichiers Ajax/Php

### UploadAjaxABCI v8.0c

Copyright (c) 20014-2022 Alain Bontemps (abciweb.net)
Licensed under the mit license (https://opensource.org/licenses/MIT)
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
- Classe de traitement des images, optimisation, redimensionnement, recadrage, filigrane
- 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écompressez le fichier et placez 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 le principe de fonctionnement.

Vous constaterez avec le tutoriel et ce premier exemple que l'on peut obtenir un formulaire complet et 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 propriétés et méthodes pour répondre aux besoins les plus divers.

Consultez les deux fichiers ci-dessous, en complément du tutoriel, pour exploiter au mieux les possibilités des classes d'upload Javascript et Php et faciliter le développement de votre code personnalisé :
- Le fichier UploadAjaxABCI.php regroupe des exemples d'utilisation des styles css événementiels et de configuration de la classe Javascript. Son fichier de destination Ajax UploadAjaxABCI_Upload.php situé dans le répertoire "Php_Upload", utilise des fonctionnalités usuelles de la classe serveur Php : renommage des fichiers, récupération des paramètres javascript, etc.
- Le fichier UploadAjaxABCI_Champs_Sup_Notation.php donne des exemples d'échange de données entre client et serveur, ajout de champs spécifiques à chaque fichier et utilisation des fonctions javascript événementielles.
Les autres fichiers d'exemples répondent à des besoins plus spécifiques.
Menu du mode d'emploi : Cliquez sur le bouton "+", à gauche du titre d'une rubrique, pour maintenir son sous-menu ouvert en permanence.
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

### Sécurité et validité des fichiers

Pour un maximum de compatibilité lors des premiers tests, certains scripts ne contrôlent pas les extensions des fichiers. Ce contrôle est indispensable si votre formulaire est destiné à un usage public non protégé.
Consultez l'exemple UploadAjaxABCI_Basique_Controle et le code source de son fichier serveur pour les méthodes disponibles. Par défaut la classe Php serveur (à partir de la version 7.5) contrôle que le type MIME du fichier correspond à son extension, cf. configuration serveur

### 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 dans les fonctions JavaScript événementielles qui renvoient toutes les propriétés disponibles sur les fichiers ainsi que le 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_Infos_Exif.php"

Cette liste n'est pas exhaustive car vous pouvez personnaliser le script avec les fonctions événementielles.

#### 1/ Classes CSS prédéfinies

- Pour afficher les informations disposant de classes prédéfinies (première liste du paragraphe 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 (principalement des retours serveur) d'ordre général.
Deux autres classes prédéfinies peuvent être utilisées pour définir des 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.
- Une classe UpAbci_inputInfosFileUnic est réservée pour renommer si besoin automatiquement les noms des champs input que vous pouvez ajouter dans les blocs d'informations spécifiques à chaque fichier. Utile par exemple pour les champs de type radio afin de permettre différentes sélections dans un upload multiple, car ce type de champ ne permet qu'une seule sélection pour tous les champs de même nom. Voir configuration du formulaire. Une fonction php getInputInfosFileUnic('index') est disponible côté serveur pour récupérer ces champs renommés.

#### 2/ Styles CSS événementiels

Pour rendre l'affichage html facilement interactif, vous disposez de styles événementiels 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 qui seront exécutées à différentes étapes du traitement des fichiers et du formulaire.

#### 4/ Exemple

Les styles css événementiels et les méthodes 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>

et

<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 sera 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 et d'interfacer le script avec des scripts externes.
En complément des informations EXIF citées plus haut, je donne plusieurs exemples de Recadrage + Upload qui utilisent le plugin "ImgAreaSelect.js", ainsi que des exemples de création de filigranes wysiwyg (direction artistique complète côté client) avec gestion de présets qui utilisent la classe interne "FiligraneABCI.js".

### Fichiers d'exemples

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

- Principe de base
  UploadAjaxABCI_Basique.php

  Principe de base et styles css événementiels.

- Exemple de base avec contrôle des fichiers
  UploadAjaxABCI_Basique_Controle.php

  Exemple de base avec contrôle des fichiers uploadés.

- Des exemples progressifs plus complets
  UploadAjaxABCI.php

  Exemples de configurations et styles css événementiels.
  Le fichier d'upload montre les principales fonctionnalités de la classe serveur d'upload, retours d'informatiosn vers le formulaire, renommage des fichiers, etc.

- Ajout de champs dans le formulaire, fonctions événementielles et retours serveur.
  UploadAjaxABCI_Champs_Sup_Notation.php

  Système de commentaires et notations, ajout de champs de saisie spécifiques à chaque fichier.
  Fonctions javascript événementielles.
  Retours d'informations serveur.

- Fonctions événementielles et retours d'informations serveur
  UploadAjaxABCI_Infos_Exif.php

  Utilisation des fonctions événementielles pour initialiser une librairie "EXIF" (installée),
  Transmission de données spécifiques aux fichiers non saisies par l'utilisateur.
  Retour d'informations serveur.

- 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 javascript.

- Traitements, redimensionnements d'images
  UploadAjaxABCI_Traitements_Images.php

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

- Création et modification d'albums photo avec miniature et photo grand format
  UploadAjaxABCI_Redimensions_Album.php

  Dialogue client/serveur avec utilisation des fonctions événementielles pour retour d'information et modifier les options du select du formulaire.
  Définition de variables de session "temporaires" valident pour la page en cours ou pour le traitement de l'upload en cours.

- Filigranes sur images multiples
  UploadAjaxABCI_Filigrane_multiple.php

  Création de filigrane textuel wysiwyg et gestion de presets, utilisation des fonctions événementielles avec la classe "FiligraneABCI" (installée).

- Filigranes et recadrages (crop) sur images multiples
  UploadAjaxABCI_Filigrane_Crop_multiple.php

  Création de filigrane textuel wysiwyg et recadrage, utilisation avancée des fonctions événementielles avec la classe "FiligraneABCI" (installée) et le plugin jQuery "imgAreaSelect" (installé).

- Crop d'images multiples
  UploadAjaxABCI_Crop_multiple.php

  Recadrage avant upload, utilisation avancée des fonctions événementielles avec le plugin jQuery "imgAreaSelect" (installé), et ajout de champs spécifiques pour chaque fichier.

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

  Recadrage avant upload, utilisation plus avancée des fonctions événementielles avec le plugin jQuery "imgAreaSelect" (installé), et ajout de champs spécifiques pour chaque fichier.

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

  Utilisation des fonctions événementielles avec le plugin jQuery "imgAreaSelect" (installé).
  Exemple à consulter notamment si l'upload n'est pas l'objet principal du formulaire.
  Le formulaire visible par l'utilisateur 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 préservées.
Faites attention d'utiliser la version jQuery 1.12.4 disponible dans le dossier "Javascript", sinon les versions 3 et plus de jQuery (actuellement utilisée dans les scripts de formulaires avec le chargement du fichier "jquery.js") ne sont compatibles qu'à partir de IE9.
Note: Ces exemples sont compatibles php 8.0 mais ils ne seront plus maintenus. Les navigateurs obsolètes inférieurs à IE10 pour lesquels ils ont été initialement concus ayant disparus du paysage informatique.

- Idem "UploadAjaxABCI_Basique.php"
  UploadAjaxABCI_Basique_CompNavObs.php

  Utilisation de la classe "UploadFormABCIServeur" spécifique aux navigateurs obsolètes.

- Idem "UploadAjaxABCI_Traitements_Images.php"
  UploadAjaxABCI_Redimensions_CompNavObs.php

  Utilisation de la classe "UploadFormABCIServeur" spécifique aux navigateurs obsolètes.

- Idem "UploadAjaxABCI_Inscription_Photo_Crop.php"
  UploadAjaxABCI_Inscription_Photo_CompNavObs.php

  Utilisation de la classe "UploadFormABCIServeur" spécifique aux navigateurs obsolètes.

## 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 de la classe 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 pour diminuer les allers-retours avec le serveur et accroître la vitesse globale des téléchargements si vous destinez l'upload à des très gros fichiers.

### Configuration du formulaire

#### 1/ Champs utilisés pour l'upload de fichiers

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

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

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. paragraphe précédent).
Pour personnaliser le bouton de sélection des fichiers, utilisez l'option de configuration Javascript config.customFileSelect décrite plus bas.

#### 2/ Ajout de champs de saisie utilisateur

Vous pouvez ajouter des champs de saisie dans le formulaire, ils seront 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 dans la super globale $_POST.
Pour ajouter des champs de saisie spécifiques à chaque fichier, placez-les à l'intérieur du bloc html ayant la classe UpAbci_infosFile. Les requêtes ajax n'enverront que les champs correspondant au fichier associé, de sorte que vous pourrez les récupérer distinctement pour chaque fichier côté serveur.
Cependant, certains champs ont besoin d'un nom unique pour chaque fichier. C'est le cas des boutons radio qui ne permettent qu'une seule sélection parmi tous les champs de même nom contenus dans le formulaire, ce qui serait incompatible avec un upload multiple puisque dans ce cas, le nom des champs spécifiques aux fichiers est dupliqué. L'attribution de la classe UpAbci_inputInfosFileUnic commande au script de concaténer le nom de l'input à l'identifiant javascript id_fich du fichier associé.
Voir le fichier d'exemple UploadAjaxABCI_Champs_Sup_Notation.php.
Note : Pour ajouter des informations spécifiques à chaque fichier non saisies par l'utilisateur, utilisez les fonctions javascript événementielles et la propriété join_file des objets passés en paramètre. Voir ce paragraphe.

### Classes prédéfinies

Ces classes prédéfinies servent uniquement à l'affichage des informations, elles sont sans incidence sur fonctionnement interne de l'upload. Elles doivent se situer à l'intérieur du formulaire ou du conteneur des résultats, déclarés respectivement en deuxième et troisième paramètre dans l'initialisation de la classe Javascript.

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

Classe | Informations / Comportements
--- | ---
UpAbci_infosServer | Retourne des informations serveur d'ordre général.
UpAbci_stopAll | Comportement 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

Classe | Conteneur des informations sur les fichiers
--- | ---
UpAbci_infosFile | Bloc 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.

Classe | Information / comportement
--- | ---
UpAbci_name | Nom du fichier
UpAbci_size | Taille du fichier
UpAbci_progressionG | Progression graphique dans une balise html <progress>
UpAbci_progressionT | Progression textuelle
UpAbci_percentage | Pourcentage effectué
UpAbci_backup | Sauvegarde effectuée (0 si upload terminé ok)
UpAbci_duration | Temps passé
UpAbci_remainingTime | Temps restant
UpAbci_status | Status en cours, ok, arrêt, erreur, éventuellement complété côté serveur
UpAbci_imgPreview | Affiche l'aperçu si c'est une image dans la limite des configurations Javascript "config.imgPreviewMaxSize" et "config.imgPreviewMaxSizeTotal".
UpAbci_inputFileName | Affiche le nom de l'input de type file
UpAbci_stop | Comportement onclick : Arrêt de l'upload du fichier
UpAbci_inputInfosFileUnic | Comportement : Renomme l'attribut name d'un champ input spécifique à chaque fichier (donc inclus dans le bloc d'information ayant la classe "UpAbci_infosFile"), en concaténant le nom de l'input à l'identifiant du fichier associé. Permet si besoin de différencier ces inputs dans le cas d'upload multiple ***

Vous pouvez écrire des valeurs par défaut dans vos éléments html d'information (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 javascript info.unitsSpacing soit "&nbsp;" par défaut.
*** Une méthode php getInputInfosFileUnic() est disponible pour récupérer la valeur de ces inputs côté serveur.

Il n'y a pas de nécessité d'attribuer la classe "UpAbci_inputInfosFileUnic" pour un champ de type text "standard" tant que le comportement du formulaire ne dépend pas de son type. Mais c'est le cas d'un bouton de type radio par exemple, voir note ci-dessus.

### 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. Ces styles vous permettent de créer un affichage dynamique en fonction du traitement des fichiers sans avoir recours à la programmation javascript.

#### 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 ainsi qu'à tous leurs éléments contenus. Le bloc des résultats n'étant pas nécessairement inclus dans le bloc du formulaire.

data-upabcicss-* | Evénement déclencheur
--- | ---
select-file | des fichiers ont été sélectionnés
error-img-prev-total | total des images supérieur à "config.imgPreviewMaxSizeTotal"
submit | le formulaire a été envoyé
submit-file | des fichiers ont été envoyés par le formulaire
upload-end | fin de traitement de tous les fichiers. Ne sera pas déclenché si aucun fichier n'a été sélectionné (voir paragraphe n°4).
backup-end | sauvegarde pour au moins un fichier en fin de traitement
form-end | fin de traitement du formulaire avec ou sans fichiers joints
infos-server | le serveur a envoyé un message vers le bloc html ayant la classe "UpAbci_infosServer"

#### 2/ Styles applicables localement

Les styles ci-dessous ont des portées spécifiques car ils sont relatifs au traitement des fichiers. Ils sont bien entendu appliquables sur tous les blocs contenus dans le bloc d'information des fichiers défini avec la classe UpAbci_infosFile ainsi que sur ce bloc lui-même.
Cependant, pour faciliter la programmation dans certains contextes, ils peuvent également être appliqués sur le bloc conteneur des résultats lui-même (troisième paramètre dans l'initialisation de la classe Javascript) et sur le bloc éventuellement défini avec la classe UpAbci_infosServer lui-même (mais pas sur ses éléments contenus).
Notez que les éléments html inclus dans le conteneur des résultats mais exclus du bloc ayant la classe UpAbci_infosFile ne seront pas ciblés par les styles ci-dessous (excepté le bloc "UpAbci_infosServer" s'il est défini).

data-upabcicss-* | Evénement déclencheur
--- | ---
error-img-prev | taille de l'image supérieure à "config.imgPreviewMaxSize"
error-img-prev-total | total des images supérieur à "config.imgPreviewMaxSizeTotal"
image-preview | image de prévisualisation disponible (si respect de la configuration javascript concernant les images)
error-user | erreur de taille ou d'extension de fichier si vous avez configuré les options javascript correspondantes.
in-progress | le fichier est en cours de traitement
backup | sauvegarde partielle disponible (ancienne ou en cours)
result | traitement du fichier terminé quelque soit la cause et le résultat
result-stop | fichier ou upload arrêté sur demande utilisateur
remaning-time-compute | s'applique après la durée de "config.remainingTimeCompute"
remaining-time-after | s'applique après la durée de "config.remainingTimeDisplayAfter"
result-ok | upload terminé ok
result-partial | upload terminé et sauvegarde existante
result-error | upload 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

- L'ordre d'écriture dans le html n'a aucune incidence.
* C'est un ordre indicatif qui peut être modifié par l'utilisation des boutons stop. Par exemple si un fichier est arrêté manuellement avant la soumission du formulaire, les "data-upabcicss-result" et "data-upabcicss-result-stop" seront appliqués, sans que "data-upabcicss-submit" ou "data-upabcicss-submit-file" n'aient été appliqués préalablement. Voir le paragraphe ci-dessous.

#### 4/ Condition d'application des styles

error-user est déclenché si la propriété fichier.upabciErrorUser du fichier est supérieure à 0. Ce style lié à la validité des fichiers sélectionnés est donc appliqué (ou non) dès la sélection des fichiers et il ne sera plus déclenché par la suite. Les styles result et result-error seront déclenchés simultanément dans l'ordre indiqué dans le paragraphe précédent.
backup est appliqué avant submit pour les fichiers sélectionnés disposant d'une sauvegarde préalable, et également après in-progress si le fichier dispose d'une sauvegarde durant le téléchargement.
result indique la fin du traitement du fichier et pourra s'appliquer avant ou après la soumission du formulaire quelque soit la cause (arrêt volontaire ou erreur, ou fin de tratement avec succès) et le résultat final (échec, échec et sauvegarde existante, succès).
result-error s'appliquera si le fichier est en erreur avant ou après la soumission du formulaire.
result-partial indique l'existence d'une sauvegarde à la fin du traitement du fichier uniquement si le fichier a été traité par le serveur. Il se distingue de backup qui peut être déclenché dès la sélection du fichier.
upload-end indique la fin de traitement de tous les fichiers. Il ne sera pas déclenché si aucun fichier n'a été soumis lors de l'envoi du formulaire, excepté si tous les fichiers valides sont arrêtés avec les boutons d'arrêt des fichiers avant la soumission du formulaire, auquel cas il sera déclenché avant le style submit.
form-end pourra toujours s'appliquer après la soumission du formulaire, avec ou sans fichiers joints et quelque soit la valeur de l'option javascript submitWithoutFile décrite ci-dessous.
1/ Si vous configurez l'option javascript submitWithoutFile avec la valeur false, alors le formulaire ne sera pas transmis en absence de fichiers joints et il ne sera pas transmis non plus si tous les fichiers sélectionnés ont été arrêtés avant l'envoi du formulaire. Dans ce cas, le style submit et les suivants ne seront pas appliqués à la soumission du formulaire, exceptés éventuellement précédemment :
- Les styles relatifs à l'arrêt des fichiers (voir ci-dessous),
- Le style upload-end si tous les fichiers valides ont été arrêtés avec les boutons d'arrêt,
- Ainsi que le style form-end après la soumission du formulaire.
2/ Les boutons d'arrêt des fichiers déclenchent les styles result et result-stop, ainsi que backup si le fichier possède une sauvegarde, et le style result-partial si le fichier possède une sauvegarde et qu'il a été traité par le serveur (toujours dans l'ordre indiqué dans le paragraphe pécédent).
3/ Les styles événementiels sont déclenchés AVANT le déclenchement des fonctions javascript événementielles, de sorte que l'utilisation de ces styles ne perturbera pas l'éventuelle programmation créée dans ces fonctions.

#### 5/ 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 boutons de sélection des fichiers durant l'upload. L'upload terminé, les boutons retrouvent leur état initial.

### Configuration de la classe Javascript UploadAjaxABCI

Notez que cette classe utilise jQuery qui doit être chargé avant le fichier UploadAjaxABCI.js.
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 | : Destination de la requête Ajax (adresse du script d'upload côté serveur)
#param2 | : Identifiant du formulaire cible, avec notation id (#mon_id) ou class (.ma_class), ou objet jQuery
#param3 | : Bloc conteneur d'information de l'upload, avec notation id (#mon_id) ou class (.ma_class), ou objet jQuery

Exemple avec la configuration de deux options de configuration javascript :

// Initialisation
var up = new UploadAjaxABCI('Php_Upload/upload.php', '#form', '.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, utilisez la méthode Start() pour lancer le script, DOM chargé
$(function(){up.Start()});

Note : Pour les navigateurs incompatibles (IE < 10), le comportement peut être paramétré avec l'option config.browserOutdeted. Voir également la méthode événementielle config.func_BrowserOutdeted qui peut être exécutée dans ce cas de figure.

## Options de configuration Javascript

### Liste des propriétés configurables

L'ordre d'écriture des options n'a pas d'incidence.
Les propriétés 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 = 250
  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, avec ou sans point (".") devant l'extension. Les variantes majuscules/minuscules sont automatiquement prises en compte. Les tableuax suivants sont donc équivalents : ['.jpg', 'JPEG', '.PNG'] = ['jpg', 'jpeg', 'png']. Si le tableau est vide aucune vérification n'est faite.
config.filesExtensionsInput = []
  Tableau des extensions autorisées pour chaque champ de type file du formulaire, avec ou sans point (".") devant l'extension. Les variantes majuscules/minuscules sont automatiquement prises en compte. La configuration requière le nom de l'input comme index et un tableau comme valeur. Par exemple si le champ se nomme "file1", la configuration pourra être : config.filesExtensionsInput['file1'] = ['jpeg','jpg','png'].
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).
config.fileSizeMaxInput = []
  Taille maximale du fichier pour chaque champ de type file du formulaire. Requière le nom de l'input comme index et une chaine de caractères comme valeur. Par exemple si le champ se nomme "file1", la configuration pourra être : config.fileSizeMaxInput['file1'] = '150Mo'. Même principe que "fileSizeMax" pour le formatage de la taille maximale.
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 second 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.inputFormAttrOnSubmit = false
  booléen false ou string 'readonly' ou 'disabled'. Si différent de false, l'attribut indiqué sera appliqué sur tous les inputs, à l'exception de ceux ayant une classe prédéfinie "UpAbci_stop" ou "UpAbci_stopAll", dès la soumission du formulaire. Les champs inclus dans le bloc conteneur renseigné en troisième paramètre dans l'initialisation de la classe javascript sont de plus formatés avec le style css "cursor:default".
  L'attribut appliqué par config.inputFormAttrOnSubmit sera supprimé à la fin du traitement du formulaire pour tous les inputs extérieurs à ce bloc, exceptés ceux pour lesquels cet attribut était déjà activé lors de la soumission du formulaire.
  Cette option de configuration sert à figer la valeur des inputs pour signifier à l'utilisateur que des modifications de données saisies ne seront pas prises en compte durant l'upload. Elle n'a pas d'influence sur le comportement du script d'upload qui enregistre dans tous les cas la valeur des inputs dès la soumission du formulaire. Voir le fichier "UploadAjaxABCI_Champs_Sup_Notation.php" pour exemple.
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 méthode "func_ImgPreviewStartAll()" pour faire afficher les vignettes dans le formulaire au moment voulu (voir le fichier d'exemple UploadAjaxABCI_Custom.php ainsi les fichiers de filigrane et de recadrage).
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. Vous pouvez mettre 0 pour donner la priorité à la hauteur maximale.
config.imgPreviewMaxHeight = 60
  En pixels (sans unités), hauteur maximale de l'aperçu image. Vous pouvez mettre 0 pour donner la priorité à la largeur maximale.
config.imgPreviewUseFileReader = false
  booléen true ou false. true utilise l'objet "fileReader" plutôt que l'objet "createObjectURL" par défaut pour créer les vignetttes de prévisualisation des images. CreateObjectURL utilise BEAUCOUP MOINS de ressources mais fileReader peut être utile dans certains cas, par exemple si vous avez besoin de copier la source de l'image générée au format base64 pour l'utiliser ultérieurement dans un autre contexte.
config.RevokeObjectURL = true
  booléen true ou false. La méthode RevokeObjectURL est utilisée pour supprimer la référence au fichier lors de la création des vignettes de prévisualisation au format Blob avec l'objet createObjectURL(), et permettre une meilleure efficacité du nettoyage des ressources. false ne supprime pas cette référence, ce qui permet par exemple de cloner l'objet "infosFile" (qui contient les informations spécifiques au fichier) pour pouvoir ensuite le déplacer dans le DOM tout en préservant la vignette de prévisualisation. A noter que vous pourriez également cloner avec succès l'objet "infosFile" si vous utiliser l'objet "fileReader" pour créer les vignettes de prévisualisation avec config.imgPreviewUseFileReader = true, mais "fileReader" consomme beaucoup plus de ressources.
config.ExifOrientationCorrection = false
  booléen true ou false. Corrige l'orientation de la vignette de prévisualisation en fonction de ses informations EXIF. Ne pas utiliser sur les nouveaux navigateurs (à partir de 2020) qui font cette correction automatiquement, sinon la vignette ne sera pas bien orientée en cas de double correction. Notez que l'orientation de l'image de prévisualisation côté navigateur n'a pas d'incidence sur le traitement php qui propose ses propres corrections.
config.infosRefresh = 1
  En seconde (sans unités), fréquence de rafraîchissement des informations textuelles.
config.remainingTimeCompute = 10
  En secondes (sans unités). 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, le style événementiel "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 d'une sauvegarde existante 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éfinie à true et qu'aucun fichier n'est soumis, permet néanmoins le déclenchement de la méthode événementielle config.func_FormEnd().
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. Si = 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 avant de modifier la valeur de cette option.
config.cookiePath = '/'
  Path du cookie. Accepte également un tableau pour indiquer le nom de domaine : ['/','domaine']. Si vous changez ces valeurs, vous devez faire de même côté serveur, soit dans l'initialisation de la classe d'upload php, soit dans ses paramètres par défaut enregistrés dans 'Php_Upload/Classes/ParamsDefautServeur.php.'
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 méthode é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 méthode événementielle "config.func_BrowserOutdeted()" - et le formulaire sera envoyé par défaut à l'adresse définie dans l'attribut "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éfinis plus bas). Les messages renvoyés dépendent du script côté serveur.
  Deux méthodes "catchErrorServer()" et "setModeDebug()" sont disponibles dans la classe d'upload Php pour gérer le retour des erreurs fatales (cf fichiers exemples de traitements d'images, de filigrane et de recadrage). Vous pouvez laisser true pour les exemples fournis car le script serveur ne renvoie que les messages personnalisés définis avec "catchErrorServer()". "setModeDebug()" renvoie tout mais ne devrait pas être utilisé en production.
config.uniqidForm = this.SHA1(this.Uniqid('UploadAjaxABCI',true))
  Valeur générée lors de l'exécution du script s'il ne trouve pas de champ nommé "UpAbci_uniqidForm" dans le formulaire. Si le champ "UpAbci_uniqidForm" est trouvé, config.uniqidForm récupère sa valeur.

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 = 'Ce fichier dépasse 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 numériques 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 peut être assez gourmande en ressources (dépend de la résolution des images et notamment si config.imgPreviewUseFileReader = true). 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. Le fait de cacher le bloc de prévisualisation par un css "display:none" n'empêcherait pas la création de la vignette même si dans ce cas elle resterait cachée. Cela dit, les smartphones sont maintenant (2022) suffisamment puissants et ne seront la plupart du temps, sauf à sélectionner simultanément de très nombreux fichiers, pas perturbés par l'affichage des vignettes de prévisualisation.
- 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, les booléens true et false, la constante null 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('Php_Upload/upload.php', '#form', '.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 méthode 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 booléens ou des valeurs numériques entourées de guillemets, vous obtiendrez le plus souvent un dysfonctionnement sans message d'avertissement préalable. Par exemple, si le booléen false est entouré de guillemets il sera considéré comme égal à true.

### 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 ou de Filigrane). L'objet "image" est passé en premier paramètre, le second paramètre contient un objet d'informations générales sur le fichier. L'objet "image" est soit l'image elle-même, soit un span de repositionnement contenant l'image dans le cas où l'image a été repositionnée en fonction de ses éventuelles informations EXIF (si config.ExifOrientationCorrection=true).
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 les exemples UploadAjaxABCI_Crop_multiple.php, UploadAjaxABCI_Filigrane_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 Filigrane et 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 méthode "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 les exemples "UploadAjaxABCI_Champs_Sup_Notation.php", "UploadAjaxABCI_Custom.php" et les exemples de Filigrane et 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. Voir cet exemple qui affiche la vitesse du téléchargement.
config.func_FileEndEach = null
  Utilisation : config.func_FileEndEach = function(objet, info_serveur, mixte_serveur){};
  Sera déclenchée à la fin du traitement de chaque fichier (voir exemple UploadAjaxABCI_Champs_Sup_Notation.php). 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 et de Filigrane).
  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 méthode 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 méthodes "catchErrorServer()" et "setModeDebug()" côté Php.
  Le troisième paramètre "mixte_serveur" contient la réponse éventuelle du serveur transmise en Php avec la méthode 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 avec javascript.
  Noter que le déclenchement de cette méthode est dépendant de la configuration des options "config.submitWithoutFile" et "config.submitWithoutFileFuncFormEnd", mais indépendant de l'option "config.queryFormEnd" qui permet d'envoyer une requête additionnelle au serveur.
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 méthode é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 méthode. A noter qu'après l'utilisation de "func_SubmitForm()" le paramètre "tableau" retourné par la méthode "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 Filigrane et 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
--- | ---
id_fich (1) | Identifiant du fichier. Utilisé pour définir le nom de l'éventuel cookie de sauvegarde, et lorsqu'on utilise la classe UpAbci_inputInfosFileUnic qui concatène le nom de l'input à cet identifiant
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. La propriété fichier.upabciErrorUser comptabilise les erreurs d'extension et de taille de fichier si vous avez configuré les options javascript correspondantes, sinon elle vaut 0. Voir la note n°2 pour un exemple de personnalisation de cette propriété et interdire l'envoi de certains fichiers en fonction de critères différents.
img_width | uniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé)
img_height | uniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé)
img_orientation | uniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé) et information disponible
img_prev_delayed | 0 si immédiat, 1 si l'affichage est différé, -1 si pas de prévisualisation
infosFile | (objet html) le bloc d'information html ".UpAbci_infosFile"
iteration | nombre 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
upAbci | (objets html) tous les objets html d'information de fichier ayant une classe ".Upabci_..."
qte_save | quantité sauvegardée en continu, y compris l'éventuelle sauvegarde initiale trouvée à la sélection du fichier
qte_save_ini | sauvegarde initiale trouvée à la sélection du fichier
qte_upload | quantité 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é. backup = sauvegarde existante
stop | 0 ou 1 (sur demande utilisateur)
stop_all | 0 ou 1 (sur demande utilisateur)
time_end | fin de l'upload en secondes et millisecondes
time_start | début de l'upload en millisecondes
inputs_infosFile | Pour info. Cette propriété existe pour des raisons techniques mais elle n'est pas nécécessaire pour la programmation de l'upload puisque tous ses éléments sont acessibles dans "infosFile". Par ailleurs elle n'est disponible qu'à la soumission du formulaire et donc pour la méthode événementielle "config.func_FormSubmit()" et suivantes.

Notes :
(1) Vous pouvez vous servir de la propriété "id_fich" qui est l'identifiant du fichier et est toujours définie. Sa composition est détaillée ici.
(2) Utilisez console.log() pour voir toutes les propriétés disponibles. 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. 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 non saisies par l'utilisateur. 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 pour sérialiser les données si vous souhaitez transmettre un tableau. En tous cas prenez soin que son contenu soit compatible avec la transmission de données dans une requête Ajax.
Le fichier "UploadAjaxABCI_Infos_Exif.php" et les exemples de filigrane et de recadrage (crop) donnent des exemples d'utilisation de cette propriété.

### Fonctions et librairies Javascript annexes

Les scripts ci-dessous, utilisés dans certains exemples, sont indépendants et se trouvent dans le dossier Javascript :

FiligraneABCI
  Classe (prototype) permettant de créer un filigrane spécifique à chaque photo y compris en cas d'upload multiple, avec contrôle complet de la direction artistique (wysiwyg) et gestion de presets. Utilisée dans les fichiers d'exemples "UploadAjaxABCI_Filigrane_multiple.php" et "UploadAjaxABCI_Filigrane_Crop_multiple.php".
DrawCanvasABCI
  Classe (prototype) permettant d'afficher un système de notation (coeurs ou étoiles) spécifique à chaque fichier, utilisée dans le fichier d'exemple "UploadAjaxABCI_Champs_Sup_Notation.php".
EXIF
  Librairie qui retourne les informations EXIF des appareils photos numériques, utilisée dans le fichier d'exemple "UploadAjaxABCI_Infos_Exif.php".
jquery.imgareaselect-10-0-rc-1
  Module jQuery permettant le recadrage des photos, utilisé dans les fichiers d'exemples "UploadAjaxABCI_Crop_multiple.php", "UploadAjaxABCI_Crop_multiple_multiple.php" et "UploadAjaxABCI_Filigrane_Crop_multiple".
MenuFixedABCI
  Classe (prototype) utilisée pour le menu du mode d'emploi dans le fichier "index.html".

Certaines fonctions internes de la classe UploadAjaxABCI 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 méthode 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
FormateOctets (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, fonctions détaillées à la fin du fichier "Javascript/UploadAjaxABCI_DEV.js"

### Code Javascript complémentaire

- Si vous souhaitez ajouter des comportements onsubmit, utilisez la méthode Javascript config.func_formSubmit, ou la méthode config.func_onFormSubmit pour intercepter l'événement puis la méthode 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 de ce processus, les événements Javascript ne seront pas réinsérés.
Utilisez les méthodes Javascript config.func_FileSelectEach ou config.func_FileSelectAll dont les paramètres retournent l'objet "event", le contexte html et des informations complètes sur tous les fichiers à chaque sélection de fichiers. Des exemples sont fournis dans les fichiers "...Notation...", "...Custom...", "...Filigrane...", "...Crop..." et "...Exif...".
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.6

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

Classes et code compatibles Php 8.0+
Fichiers exemples dans le dossier "Php_Upload".
L'adresse des fichiers cités dans cette rubrique est donnée par rapport à ce dossier.
Par défaut, la classe d'upload serveur (version >= 7.5) contrôle que le type MIME du fichier correspond à son extension.
Exemple de configuration basique * :

<?php
session_start();
// Charge les classes php avec spl_autoload_register
spl_autoload_register(function ($class) {require 'Classes/' . $class . '.php';});
// Initialisation de la classe php d'upload avec le dossier de destination en premier paramètre
$up = new UploadAjaxABCIServeur('../Destination_Upload1/');
// getParam("uniqid_form") renvoie l'identifiant de formulaire pour la vérification ci-dessous
$uniqid_form = $up->getParam("uniqid_form");
// Vérification du token qui assure que ce script est appelé depuis le formulaire. Permet également de renvoyer un message en cas de timeout du serveur, connexion perdue ou non valide.
if(!(isset($uniqid_form,$_SESSION['UploadAjaxABCI'][$uniqid_form]['token'])))
{
$up->exitStatusErreur(SetMessages::get('UpAbVerifToken'));
}
// 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 (c.f "UploadAjaxABCI_Upload.php" pour des exemples).
$up->Upload();
$up->Transfert();
// Indispensable en fin de script, "exitReponseAjax()" retourne les informations nécessaires pour la classe javascript.
$up->exitReponseAjax();
?>

* Notez que cet exemple ne comprend aucun contrôle sur les extensions des fichiers.

Consultez l'exemple UploadAjaxABCI_Basique_Controle et son fichier serveur pour le contrôle des fichiers.

### Configuration de la classe Php UploadAjaxABCIServeur

$up = new UploadAjaxABCIServeur($dossier_destination=null, $dossier_temporaire=null, $cookie_options=null, $extensions=null, $max_size=null, $verif_type_MIME=null)

$dossier_destination | Dossier de destination de l'upload. Si ce paramètre n'est pas renseigné ou égal à la constante null, la destination sera celle renseignée dans la classe "ParamsDefautServeur". Ce paramètre sera utilisée par défaut si vous n'indiquez pas l'adresse de destination du fichier dans la méthode Tranfert().
$dossier_temporaire | Dossier dans lequel sont compilés les fragments de fichiers. Ce dossier est également utilisé pour la vérification du type de tous les fichiers, y compris ceux ayant une taille inférieure à taille maximale d'un fragment, afin de contrôler le type MIME du fichier tel qu'il est enregistré sur le serveur, avant de le déplacer vers son emplacement définitif (cf. paramètre 'verif_type_MIME').
$cookie_options | Le tableau des options du cookie. Identique au tableau d'options de la fonction native de php, excepté pour le premier paramètre "expires" remplacé par l'index "duration" qui indique la durée de validité du cookie exprimé en secondes, et non pas sa date d'expiration. Tous les index du tableau doivent être renseignés. Si vous modifiez les options "path" ou "domain" du cookie, vous devrez faire de même en configurant l'option "config.cookiePath" lors de l'initialisation de la classe javascript.
$extensions | Vérifie si l'extension du fichier correspond à un élément du tableau passé en paramètre. Si non, supprime le fichier et retourne un message d'erreur. Si tableau vide, aucun contrôle n'est fait. Les extensions sont insensibles à la casse, précédées ou non d'un point et les espace de début ou de fin seront nettoyés. Les tableaux suivants sont donc équivalents ['jpg','jpeg','png'] = ['.JPG',' .JPEG ', ' .png']
$max_size | Si différent de null, vérifie que le poids du fichier n'excède pas la taille autorisée passée en paramètre. Si sa taille est supérieure, supprime le fichier et retourne un message d'erreur. Attend un nombre en octets ou en octets formaté ex: 800K, 10 Mo ou 1.2 g (les espaces sont autorisés entre le nombre et son unité qui est insensible à la casse et peut être, ou non, suivie du caractère "o"). Les nombres décimaux sont acceptés.
$verif_type_MIME | Vérifie que le type MIME du fichier correspond à son extension. Si non, supprime le fichier et retourne un message d'erreur. Utilise par défaut la variable d'environnement MAGIC du serveur. Si égal = false, ce contrôle est désactivé (ne devrait être envisagé que dans des espaces sécurisés). Supporte également un tableau associatif avec l'index 'path_MAGIC_MIME' pour spécifier une autre base magique que celle utilisée par défaut, et/ou l'index 'except' qui attend un tableau pour désactiver le contrôle de certains fichiers. ["path_MAGIC_MIME" => "chemin/specifique"]; ["except" => ["MTS","mt2s"]]; // extensions à ne pas contrôler (mêmes possibilités pour le formatage des extensions que pour le paramètre $extensions). ["path_MAGIC_MIME" => "chemin/specifique", "except" => ["MTS", "mt2s"]]; // Chemin spécifique + ne contrôle pas les fichiers .mts et .mt2s. Si vous désactivez ce contrôle pour certains fichiers, a fortiori pour tous, il est vivement conseillé de le faire uniquement pour la configuration de la classe dans votre script d'upload, et non pas dans le trait "ParamsDefautServeur", car rien ne permettra de vous le rappeler par la suite avec des tests de fonctionnement standards, tant que vous ne modifiez pas volontairement l'extension de certains fichiers pour constater qu'ils sont acceptés et donc que ce contrôle est désactivé.

Note : L'adresse des dossiers passés en paramètre doit comporter un séparateur final, ex:

$dossier = '../Destination/';

Configuration avec un tableau (recommandé)

Pour plus de souplesse et de lisibilité, vous pouvez configurer la classe avec un tableau en reprenant les mêmes index que les variables ci-dessus. Par exemple pour configurer le dossier de destination, les extensions autorisées et la taille maximale:

$config = [
'dossier_destination' => '../mon_dossier/',
'extensions' => ['mp4', 'divx', 'flv', 'mkv'],
'max_size' => '500 Mo'
];
$up = new UploadAjaxABCIServeur($config);

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" pour définir les valeurs par défaut - tous les paramètres de cette classe serveur ont des valeurs par défaut définies dans la méthode 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, c'est à dire qu'une valeur renseignée et vide comme '' sera prise en compte si compatible avec le paramètre. Sinon, les paramètres définis dans ParamsDefautServeur seront utilisés.
Dans les exemples, je définis toujours le dossier de destination pour plus de clarté.

### Récupération des champs du formulaire

Vous pouvez récupérer les valeurs de vos champs input éventuellement ajoutés dans le formulaire, dans la super globale $_POST.

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

Les champs avec la notation tableau sont également acceptés.
Notez que tous les champs input ajoutés à l'extérieur du bloc html ayant la classe UpAbci_infosFile seront transmis dans toutes les requêtes ajax, donc également pour chaque fichier uploadé dans le cas d'un upload multiple.
Si vous avez inséré des champs à l'intérieur du bloc html ayant la classe UpAbci_infosFile, ces champs sont spécifiques à chaque fichier et les requêtes ajax ne transmettront que les champs associés au fichier correspondant. Ainsi en cas d'upload multiple, il n'y a pas de confusion avec ceux de même nom associés aux fichiers précédents/suivants et vous pouvez les récupérer de manière classique :

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

Si à l'intérieur du bloc html ayant la classe UpAbci_infosFile, vous avez inséré des champs en leur attribuant la classe UpAbci_inputInfosFileUnic pour les rendre unique (afin par exemple de permettre leur sélection, cas des boutons radio dans un upload multiple), vous pouvez utiliser la méthode php getInputInfosFileUnic($nom_du_champ) pour récupérer la valeur de ces champs :

$radio = $up->getInputInfosFileUnic('radio');

### 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 :

NOTE 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" détaillé ci-dessous.
$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. 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_inputsInfosFile
  Tableau qui permet de récupérer la valeur des champs spécifiques à chaque fichier dans l'éventuelle requête additionnelle si l'option de configuration Javascript config.queryFormEnd = true. En dehors de la requête additionnelle, ces champs sont dans la super globale $_POST et la variable UpAbci_inputsInfosFile n'est pas définie.
$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 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 ou unique 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.

Liste des index des tableaux $UpAbci_form et $UpAbci_formEnd :

Dans tous les cas |
--- | ---
id_form | L'identifiant, id ou classe du formulaire. Retourne une chaine de caracatère de forme "#id" ou ".classe"
uniqid_form | L'identifiant unique du formulaire (token)
iteration_form | Nombre 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 |
input_name | Nom de l'input de type file
id_fich | Identifiant du fichier. Utilisé pour définir le nom de l'éventuel cookie de sauvegarde, et lorsqu'on utilise la classe UpAbci_inputInfosFileUnic qui concatène le nom de l'input à cet identifiant
name | Le nom du fichier
size | La taille du fichier
type | Le type du fichier
lastModified | La valeur de "lastModified"
qte_save | Quantité sauvegardée en continu
qte_upload | Quantité 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_start | Début de l'upload en millisecondes
time_end | Fin de l'upload en secondes et millisecondes
iteration | Nombre d'itérations de la requête Ajax pour le fichier
join_file (2) | Contenu de $UpAbci_joinFile
inputs_infosFile (2) | Uniquement disponible dans le tableau $UpAbci_formEnd Contenu des champs inputs éventuellement inclus dans le bloc html ayant la classe UpAbci_infosFile (informations spécifiques à chaque ficher). En dehors de la requête additionnelle, ces inputs sont disponibles dans la super globale $_POST (voir paragraphe précédent).

(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, les tableaux $UpAbci_form et $UpAbci_formEnd ne contiennent pas initialement ces index. La classe serveur les ajoute automatiquement dans ces tableaux à réception de la requête Ajax pour pouvoir récupérer toutes les informations utiles en listant simplement ces tableaux.
- 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

- Aucune fonction n'est fournie pour récupérer les valeurs de $UpAbci_formEnd (autres que "id_form", "uniqid_form" et "iteration_form") car c'est un tableau de tableaux, un par fichier. Faites une boucle sur ce tableau pour lister les différents fichiers et récupérer les informations associées aux index.

foreach($up->UpAbci_formEnd as $file) {
// Si le fichier est correctement uploadé
if($file['result'] == "ok_done") {
//...
}}

- 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.

### 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_Upload_....php.
La classe UploadAjaxABCIServeur utilise le trait ParamsDefautServeur qui définit la configration par défaut, ainsi que le trait de services UploadABCITraitServices qui regroupe des fonctions souvent utilisées dans les scripts d'upload. La classe UploadABCIServices utilise ce même trait de services afin d'exploiter plus facilement ces fonctions dans les scripts de formulaires côté client.
L'ordre d'application de ces méthodes est important. Si vous utilisez des fonctions nécessitant l'existence d'un fichier, assurez-vous de sa présence avec la méthode getFragment(). Cependant, certaines méthodes usuelles comme Upload() et Transfert() font automatiquement ce contrôle.

Méthodes de la classe UploadAjaxABCIServeur

catchErrorServer ($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.
getInputInfosFileUnic($name)
  Récupération des valeurs des champs inputs ayant la classe UpAbci_inputInfosFileUnic.
getFileEnd ()
  Retourne TRUE si c'est la fin du fichier sinon FALSE. Retourne NULL 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 méthode "getTempAdressFileComplete()" après la méthode "Upload()" pour avoir confirmation que le fichier est complet et correctement enregistré dans le dossier temporaire du serveur ou "getTransfertOk()" après la méthode "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 méthode "Upload()" sinon elle est inopérante. Cette méthode 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é en lui appliquant la méthode "cleanFileName()".
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. Peut également être récupéré en second paramètre des fonctions Javascript événementielles config.func_FileEndEach et config.func_FormEnd
  Attention ! Pour un maximum de possibilités, le contenu est inséré avec la méthode jQuery "html()", vous devez donc protéger les variables utilisateur contenues dans ce message avec htmlspecialchars() pour éviter que des caracatères spéciaux comme "<" soient interprétés comme du html, ce qui produirait une rupture dans l'affichage du message ou du formulaire.
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 vous avez utilisé l'option de configuration Javascript config.queryFormEnd = true, la requête de confirmation de fin de traitement du 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 status 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 ou tableaux précédemment ajoutés avec les méthodes "addInfosServer()" ou "addMixteServer()", pour ce faire utilisez plutôt la méthode "addStatusErreur($value)".
addStatusErreur($value)
  Ajoute un message qui sera concaténé au status 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.
  Notez que la méthode "Transfert()" redéfini le status du fichier. Faites une condition sur la méthode "Transfert()" si vous voulez qu'elle n'écrase pas le status précédemment défini avec la méthode "addStatusErreur".
Upload()
  Initialise l'upload du fichier ou du fragment de fichier et suivant les cas, compile les fragments dans un fichier temporaire. Cette méthode contrôle en interne qu'un fichier ou un fragment de fichier est présent dans la requête et ne fait rien dans le cas contraire.
getTempAdressFileComplete()
  A utiliser APRES la méthode "Upload"
  Retourne l'adresse du fichier temporaire s'il est complet et valide sinon false. Notez que les fichiers temporaires n'ont pas d'extension.
getTempAdressFile()
  A utiliser APRES la méthode "Upload"
  Retourne l'adresse du fichier temporaire après l'utilisation de la méthode "Upload". Peut être un fragment de fichier. Notez que les fichiers temporaires n'ont pas d'extension.
deleteCookieSave()
  Supprime le cookie de sauvegarde. Utilisé en interne. Utilisez plutôt "deleteFileTempCookie()", car si le cookie de sauvegarde est supprimé, le fichier temporaire ne sera probablement plus utile.
deleteFileTempCookie()
  A utiliser APRES la méthode "Upload"
  Supprime le cookie de sauvegarde et le fichier temporaire. Peut être utilisée dans différents contextes, lorsque le fichier n'est plus utile ou non valide ou dans le contexte d'une configuration sans utilisation de la méthode "Transfert()", cf. Upload sans Transfert().
setTransfertOk()
  Renvoie le status ok à la classe javascript. A utiliser dans le contexte où la méthode "Transfert" n'est pas nécessaire pour transférer le fichier vers son emplacement définitif, cf. Upload sans Transfert().
SetTransfertOkDelFileTempCookie()
  Raccourci pour appliquer les deux méthodes "setTransfertOk" et "deleteFileTempCookie" souvent employées conjointement lorsqu'on utilise pas la méthode "Transfert", cf. Upload sans Transfert().
Transfert($file_destination=null)
  A utiliser APRES la méthode "Upload"
  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 dossier de destination passé en argument dans l'initialisation de la classe d'upload et le nom du fichier nettoyé, soit la même valeur que "getFileDestination()". Cette méthode contrôle en interne que le fichier est complet et ne fait rien dans le cas contraire.
  Important : voir le paragraphe Upload sans Transfert() si vous n'utilisez pas cette fonction dans votre script d'upload.
addStatusOk($value)
  A utiliser normalement APRES la méthode "Transfert"
  Ajoute un message qui sera concaténé au status info.status.ok de la classe Javascript et envoyé dans le bloc html ayant la classe UpAbci_status.
getTransfertOk()
  A utiliser APRES la méthode "Transfert".
  A le même effet que de tester le retour de la méthode "Transfert". Retourne true si le fichier est complet et a été déplacé avec succès vers son emplacement définitif, sinon false.
setChmod($adress_file, $droits)
  Attribue les droits d'accès au fichier. Consultez la doc php -> chmod pour le paramètre "$droits". 0604 est souvent suffisant pour donner l'accès en lecture des fichiers (cela peut varier suivant les serveurs). En cas d'erreur, sort du script en envoyant un message d'erreur.
exitReponseAjax()
  Retour d'information INDISPENSABLE pour le script Ajax excepté si la méthode "exitStatusErreur" a été utilisée. On peut alternativement utiliser la méthode "getReponseAjax" suivant le contexte.
getReponseAjax()
  Alternative à la méthode "exitReponseAjax". Retourne les informations nécessaires pour le retour Ajax mais ne sort pas du script Php.

Fonctions implémentées par le trait UploadABCITraitServices

formateOctets ($octets, $espace=' ', $type=true)
  Retourne une chaine formatée à partir d'un nombre d'octets. $espace permet d'indiquer l'espacement entre le nombre retourné et son unité, suivie éventuellement du caractère "o" si $type vaut true. Cette fonction est l'inverse de la méthode "returnOctets".
setCookie($name, $value, $options)
  Permet d'envoyer un cookie avec l'option "samesite" quelque soit la version php utilisée. Utilise la même syntaxe que la fonction native de Php. Le tableau $options doit être fourni et tous ses index doivent être renseignés, c.f doc Php. Notez que le cookie utilisé par la classe serveur php doit impérativement être configuré avec l'option httponly=false pour pouvoir être récupéré par la classe javascript.
getUniqid ($length = 32)
  Retourne un identifiant aléatoire "unique". Basé sur la fonction php "random_bytes", ou si non disponible utilise "openssl_random_pseudo_bytes". On admet généralement que l'identifiant sera unique à partir de $length = 16.
returnOctets ($val)
  Retourne des octets depuis une chaîne formatée comme 25ko ou 100 Mo ou 1.2 g
  Les valeurs décimales sont supportées avec un point ou une virgule comme séparateur. Des espaces peuvent exister, ou non, entre les valeurs et leurs unités qui sont par aillleurs insensibles à la casse et peuvent être, ou non, suivies du caractère "o".
getExtension($nom_fichier)
  Retourne l'extension du fichier en minuscules. Attention, ne pas utiliser sur le retour des méthodes "getTempAdressFile()" ou "getTempAdressFileComplete()" car les fichiers temporaires ne possèdent pas d'extension.
cleanTabExtensions($tab_extensions)
  Retourne un tableau d'extensions en minuscules après avoir supprimé les éventuels points et espaces des extensions. Par exmple ['.jpg', ' JPEG', ' .PNG '] retournera ['jpg', 'jpeg', 'png'].
verifExtensions($nom_fichier, $extensions)
  A utiliser de préférence AVANT la méthode "Upload" (si vous l'utilisez après, le fichier sera téléchargé inutilement dans le répertoire temporaire avant que le visiteur puisse avoir l'information).
  $nom_fichier peut être récupéré par la méthode "getParam('name')" ou la méthode "getCleanFileName()".
  $extensions est un tableau d'extensions autorisées. Il est traité en interne par la méthode "cleanTabExtensions()", les extensions peuvent donc être, ou non, précédées d'un point et sont insensibles à la casse. Si le tableau est vide, aucune vérification n'est faite. Sauf besoins particuliers, il est plus pratique de configurer les extensions autorisées dans l'initialisation de la classe d'upload.
getMimeType($adresse_fichier, $path = null)
  A utiliser APRES la méthode "Upload". Notez que par défaut, la classe serveur utilise cette fonction pour vérifier si le type MIME du fichier correspond à son extension.
  Retourne le type MIME du fichier. Utilisez la méthode "getTempAdressFile()" pour définir $adresse_fichier. $path permet d'indiquer une autre base magique que celle utilisée par défaut.
renameIdenticName($adresse_fichier, $incr = false, $unix = false)
  Renomme le fichier si un fichier de même nom existe déjà sur le serveur.
  A utiliser AVANT la méthode "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.
  - Par défaut la fonction ajoute un identifiant unique (uniqid) au nom des fichiers.
  - Avec un second paramètre optionnel non null et différent de false, ex : $up->renameIdenticName($destination_fichier,'incr'); le nom des fichiers est incrémenté.
  - Un troisième argument optionnel casse sensitive est également disponible pour compléter le paramétrage du mode incrémentiel, mais à n'utiliser que sur les serveurs casse sensitive (NE PAS UTILISER AVEC LES SERVEURS WINDOWS).
cleanFileName($chaine)
  Retourne $chaine après avoir supprimé ou remplacé les caractères spéciaux ou accentués et les espaces vides. Permet d'obtenir un nom de fichier standardisé et accessible quelque soit le nom initial. Voir détails de cette fonction dans le fichier "Php_Upload/Classes/UploadABCITraitServices.php".

Fonctions implémentées par le trait ParamsDefautServeur

getParamUploadAjaxABCIServeur()
  Retourne un objet des paramètres utilisés par défaut par la classe d'upload. Voir détails de cette fonction dans le fichier "Php_Upload/Classes/ParamsDefautServeur.php".
getParamConnectBdd()
  Cette fonction est en mode protected, elle n'est pas utilisée dans la classe d'upload serveur mais uniquement dans la classe "C_PDO".

### Retours d'informations serveur

Parmi les méthodes détaillées ci-dessus, six méthodes sont disponibles pour retourner des informations vers le formulaire, la sixième est nécessaire dans tous les cas.
addStatusOk ($value)
addStatusErreur ($value)
exitStatusErreur ($value)
Envoient une information (texte ou html) dans le status du fichier (bloc html ayant la classe UpAbci_status). Elles définissent de plus les styles événementiels qui seront appliqués dans le html avec data-upabcicss-result, et data-upabcicss-result-ok ou data-upabcicss-result-error suivant la méthode appliquée.
addInfosServer ($value)
Envoie une information (texte ou html) dans le bloc ayant la classe UpAbci_infosServer. Le style événementiel data-upabcicss-infos-server sera appliqué dans le html. Voir le fichier "UploadAjaxABCI_Upload.php" dans le dossier "Php_Upload" pour exemple.
Important : Le contenu retourné par les méthodes addStatusOk, addStatusErreur, exitStatusErreur et addInfosServer, est inséré dans le html en utilisant la méthode html() de jQuery pour un maximum de possibilités. Aussi si certaines variables retournées sont susceptibles de contenir des caractères spéciaux qui sont interprétés comme des tag html ("<" et ">" par exemple), vous devez protéger ces variables côté serveur avec la fonction Php htmlspecialchars() sinon le html final pourra être déformé et la réponse vide.
addMixteServer ($value)
En complément des méthodes précédentes qui ne nécessitent pas l'utilisation de fonctions javascript événementielles côté formulaire puisqu'elles ont un comportement prédéfini pour modifier directement le html, vous disposez de la méthode addMixteServer() dont vous pouvez récupérer le contenu en troisième paramètre des méthodes javascript événementielles config.func_FileEndEach et config.func_FormEnd.
Cela vous permet de retourner tout type de contenu (tableau, html ou texte) qui pourra être exploité en javascript selon vos besoins par l'intermédiaire de ces fonctions événementielles.
Voir le fichier UploadAjaxABCI_Champs_Sup_Notation pour exemple.
exitReponseAjax ()
Doit être utilisée dans tous les cas en fin du script d'upload php. Elle compile les différents messages, état du serveur, état des fichiers, dans un tableau json avec les informations nécessaires à la bonne continuité du script d'upload javascript. Elle défini également les messages et comportements par défaut qui seront retournés en absence d'utilisation des méthodes précédentes. Cette méthode doit être présente en fin de script mais vous n'avez pas à la configurer.

### Gestion des messages

Tous les messages utilisés par les scripts et les classes php sont centralisés sous forme de tableaux dans la classe Messages, voir le fichier "Classes/Messages.php". La classe SetMessages qui hérite de cette classe, construit un tableau des messages nécessaires en compilant certains de ces tableaux suivant les besoins des classes php utilisées.
1/ Vous pouvez ajouter des tableaux personnalisés inclus dans la classe Messages, en complément de ceux qui sont automatiquement chargés, en intanciant la classe SetMessages dans vos scripts d'upload :

// Ajoutera les tableaux de messages retournés par les propriétés 'inscription' et 'verifFileExist' de la classe 'Messages'.
new SetMessages('inscription', 'verifFileExist');

Notez qu'en cas de conflit, les index déjà existants ne seront pas remplacés.
- Pour des besoins spécifiques, utilisation de "setMessages" en dehors du contexte d'un upload :
L'argument réservé nommé "notIni" sert à éviter que le tableau "$communs" - qui regroupe les messages les plus communs utilisés dans les scripts d'upload - soit chargé automatiquement lors de l'instanciation de "SetMessages".

new SetMessages('inscription', 'verifFileExist', 'notIni');

2/ Comme montré en exemple dans les scripts serveur, la classe SetMessages propose une méthode get pour récupérer les messages :

/* Récupère le message ayant l'index 'UpAbExtensionFichier' enregistré dans la classe
"Messages" qui signale une erreur d'extension de fichiers, et le fait afficher comme
erreur dans le status du fichier avec exitStatusErreur (cf. chapitre précédent) */
$up->exitStatusErreur (SetMessages::get('UpAbExtensionFichier'));

3/ La méthode surchargeMessages($tab) permet d'ajouter ou de surcharger les messages du tableau créé par SetMessages. C'est pratique pour proposer des traductions ou des messages simplifiés pour les visiteurs qui n'ont pas besoin de messages détaillés (dont certains sont utilisés pour faciliter le debug), tout en préservant les autres messages de la classe Messages.
Notez qu'en utilisant cette méthode, les index déjà existants seront remplacés.
Par exemple, ci-dessous "$traduct_messages" qui est un tableau de messages traduits en fonction de la langue du visiteur avec ici 7 messages qui me permettront de gérer un téléchargement de fichiers, avec redimensionnement et sauvegarde du fichier original si le fichier est une image, ainsi qu'un contrôle des champs requis :

/* Je construis avec $tab_trad, un tableau de messages existants dans la classe "Messages"
dont les valeurs sont à remplacer*/
$tab_trad = [];
foreach ($traduct_messages as $index => $value)
{
switch ($index)
{
case "connexion_perdue" :
$tab_trad['UpAbVerifToken'] = $value;
break;
case "file_exced_max_serveur" :
$tab_trad['UpAbMaxSizeFichier'] = $value;
$tab_trad['UpAbAllowedMemorySize'] = $value;
$tab_trad['UpAbMaximumExecutionTime'] = $value;
break;
case "file_ext_novalid" :
$tab_trad['UpAbExtensionFichier'] = $value;
break;
case "Image_non_valide" :
$tab_trad['UpAbImageNonValide'] = $value;
break;
case "pb_traitement_fichier" :
$tab_trad['UpAbConfigChmod'] = $value;
$tab_trad['UpAbCopieFichier'] = $value;
$tab_trad['UpAbServerFichierTemp'] = $value;
$tab_trad['UpAbServerVerifFile'] = $value;
break;
case "pb_traitement_image" :
$tab_trad['UpAbImageCorrectionExifJpg'] = $value;
$tab_trad['UpAbImageCreationSource'] = $value;
$tab_trad['UpAbImageCreationDestination'] = $value;
$tab_trad['UpAbImageRedimension'] = $value;
$tab_trad['UpAbImageEnregistrement'] = $value;
break;
/* Ajoute ici un message avec un index 'formIncomplet' non existant
dans les différents tableaux de la classe "Messages"*/
case "formulaire_incomplet" :
$tab_trad['formIncomplet'] = $value;
break;
}
}
//On utilise ensuite la méthode "surchargeMessages" pour ajouter ce tableau dans "SetMessages"
SetMessages::surchargeMessages ($tab_trad);

En cas de problème dans le traitement d'une image, les messages indexés avec 'UpAbImageCorrectionExifJpg', ..., 'UpAbImageEnregistrement' utilisés éventuellement en cas de bug par les fonctions de traitement d'images, renverront la valeur de l'élément "pb_traitement_image" du tableau de traduction "$traduct_messages".
Par ailleurs, si un champ requis est manquant dans le formulaire, je pourrai récupérer le message avec la méthode get de SetMessages, et si je veux le faire afficher dans le bloc html ayant la classe UpAbci_infosServer :

$up->addInfosServer (SetMessages::get('formIncomplet'));

Important : Les messages ajoutés avec surchargeMessages sont protégés et ne seront donc pas remplacés par les classes qui seront appelées dans la suite du script et qui initialisent automatiquement des messages. Vous devez donc utiliser cette méthode en haut de votre script php d'upload, avant toute utilisation de la méthode get de SetMessages et d'initialiser la classe d'upload ou d'utiliser d'autres classes (de redimensionnement ou de crop par exemple) qui l'utilisent en interne, afin que vos messages personnalisés soient utilisés prioritairement.
Ce principe vous permet de garder une bonne maitrise de la gestion des erreurs. Au pire, si vous avez homis de traduire un message qui a besoin d'être affiché, il sera non traduit mais néanmoins affiché avec la valeur initiale contenue dans la classe Messages.
- Pour des besoins spécifiques, utilisation de "setMessages" en dehors du contexte d'un upload :
Un second paramètre optionnel, si = false : SetMessages::surchargeMessages ($tab_trad, false), sert à éviter que le tableau "$communs" - qui regroupe les messages les plus communs utilisés dans les scripts d'upload - soit chargé automatiquement par la méthode "surchargeMessages".

### Upload sans Transfert(), fichier temporaire

1/ Dans certains cas, vous n'aurez pas besoin d'utiliser la méthode Transfert() qui déplace le fichier temporaire vers son emplcement définitif. Par exemple le fichier uploadé peut être exploité sans nécessairement avoir besoin d'être sauvegardé, ou lorsque vous utilisez la classe ImgGD qui possède sa propre méthode "export()" pour créer et exporter des fichiers images. La méthode Transfert() effectue en interne les tâches suivantes, la première étant indispensable pour une bonne continuité du script côté client :

- Enregistrement de l'état du fichier en cours pour le retour Ajax et les informations HTML
- Effacement du cookie de sauvegarde du fichier en cours
- Transfert du fichier temporaire vers son emplacement définitif (voir fin de ce paragraphe).

Si donc vous n'utilisez pas la méthode Transfert(), vous devez utiliser les méthodes setTransfertOk() (renvoie le status "ok" qui sera utilisé par la classe javascript) et deleteFileTempCookie() (supprime le fichier temporaire et le cookie de sauvegarde), pour faire les tâches équivalentes, ou par facilité, la méthode SetTransfertOkDelFileTempCookie() qui regroupe ces deux méthodes souvent utilisées conjointement.
Notez que si vous n'utilisez pas la méthode deleteFileTempCookie(), le visiteur retrouvera la sauvegarde dès la prochaine sélection de son fichier. Cela peut être une solution pour préserver l'upload d'un fichier en attente d'informations complémentaires (si besoin on peut avoir une sauvegarde pour tous les fichiers en utilisant la méthode "saveAll"). Vous pourriez alternativement utiliser la méthode deleteCookieSave() pour supprimer le cookie de sauvegarde tout en préservant le fichier temporaire dans des cas particuliers. Tout dépend de vos besoins, mais renseignez au minimum le status du fichier pour une bonne continuité du script javascript.
Si vous n'utilisez pas la méthode "Transfert()" et que vous ne renseignez pas le status du fichier avec la méthode "setTransfertOk()", la classe d'upload javascript renverra le message "Echec du traitement", même si le traitement php s'est effectué correctement. Vois l'exemple ci-dessous pour différents cas de figure.
$dossier_destination = ''; // Dans ce cas de figure, ce paramètre ne sera pas utilisé
//...
$up = new UploadAjaxABCIServeur($dossier_destination);
//...
$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 ok on utilise la méthode setTransfertOk() pour la continuité du script javascript et les informations HTML,
et deleteFileTempCookie() si le fichier est devenu inutile:
*/
$up->setTransfertOk();
$up->deleteFileTempCookie();
/*
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 (à utiliser en complément de "setTransfertOk()" et non
en remplacement):
*/
//$up->addStatusOk('Mon message ok personnalisé');

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

2/ Le dossier temporaire "Upload_Temp" est utilisé pour compiler les fichiers dont la taille est supérieure à celle des fragments (définie côté client dans le formulaire et transmise à la classe php dans la requête ajax). A noter qu'il est également utilisé systématiquement quelque soit la taille des fichiers pour stocker les fichiers en attente de transfert si vous utilisez la méthode "saveAll()", ou si vous ne désactivez pas le contrôle du type MIME qui est activé par défaut.
En cas de panne internet durant l'upload d'un gros fichier, ou si le visiteur arrête l'upload d'un fichier durant son transfert et ne le reprend pas par la suite, vous aurez des fragments de fichiers inutiles dans ce répertoire, de même que dans l'exemple ci-dessus si vous n'utilisez pas la méthode "Tranfert()" ni la méthode "deleteFileTempCookie()". Voir le chapitre Technique d'upload, maintenance qui propose deux méthodes de nettoyage. La fonction NettoyageTemp::interval(); est intégrée dans tous les scripts côté formulaire depuis la version 7.6b.

### 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 dans les fichiers d'exemples avec "spl_autoload_register".
- Les classes UploadAjaxABCIServeur, UploadFormABCIServeur et UploadABCIServices utilisent le trait UploadABCITraitServices.
- Les classes UploadAjaxABCIServeur, NettoyageTemp et C_PDO utilisent le trait ParamsDefautServeur.
- La classe SetMessages hérite de la classe Messages et est utilisée un peu partout dans les scripts d'exemples et dans les classes elles-mêmes. Notez qu'elle propose une méthode surchargeMessages qui permet de personnaliser/traduire ou ajouter des messages depuis vos scripts d'upload sans modifier la classe Messages. Voir le paragraphe précédent.
- Les classes ImgGD, CorrectionExifJpg, et C_PDO peuvent émettre des exceptions, aussi vous devez les utiliser dans un bloc try/catch (cf. fichiers d'exemples code serveur dans le dossier "Php_Upload").

UploadAjaxABCIServeur
  Classe serveur ajax (détaillée plus haut) liée à la classe javascript "UploadAjaxABCI.js".
ParamsDefautServeur
  Trait incluant les paramétrages par défaut de la classe "UploadAjaxABCIServeur" et de la classe "C_PDO".
Messages
  Classe de centralisation des messages.
SetMessages
  Hérite de la classe Messages. Classe de chargement et de sélection des messages.
ImgGD
  Classe de traitement des images, optimisation, redimensionnement, recadrage, filigrane (utilise la bibliothèque GD). Détaillée dans le paragraphe suivant.
C_PDO
  Classe de connexion BDD. Pensez à modifier la métohde "getParamConnectBdd" du trait "ParamsDefautServeur" si vous utiliser cette classe.
CorrectionExifJpg
  Corrige l'orientation des images jpg suivant ses informations EXIF (utilise la bibliothèque GD).
  Ne pas utiliser conjointement aves la classe ImgGD qui possède sa propre gestion
  de l'orientation initialisée automatiquement en interne.
NettoyageTemp
  Classe de nettoyage du dossier temporaire. Voir détail
UploadABCITraitServices
  Trait de services, fonctions utilitaires communes dans un upload, utilisé dans la classe serveur.
UploadABCIServices
  Classe de services, utilise le trait "UploadABCITraitServices" pour un usage facilité côté client.
SymfonyMapType
  Classe de correspondance entre les types et les extensions, utilisée pour le contrôle du type MIME. Conservez la même structure si vous mettez à jour le tableau $map.
UploadFormABCIServeur
  Classe serveur pour navigateurs obsolètes (détaillée plus bas).
Validateur
  Classe de validation des champs d'un formulaire.

Note : Les classes "CropRedim" et "RedimImage" ne sont plus utilisées depuis la version 8.0 de ce module d'upload, excepté dans les exemples de code pour navigateurs obsolètes. Elles ont été remplacées par la classe ImgGD beaucoup plus conviviale avec plus de possibilités, mais elles ont néanmoins été mises à jour pour php 8.0 et sont conservées dans le répertoire "Php_Upolad/Classes" pour que les utilisateurs de ces anciennes classes puisse facilement mettre leur code à jour. N'utilisez plus ces fonctions pour vos prochains développements car elles ne seront plus maintenues et sont par ailleurs beaucoup plus complexe à paramétrer.

### Traitement des images, classe ImgGD

Cette classe qui utilise la librairie GD de php, permet d'optimiser des images pour le web, de faire des redimensionnements, des recadrages, et d'appliquer des filigranes textuels sur l'image.
Les formats supportés sont "jpg", "jpeg", "png" et "gif".
Elle s'initialise en passant l'adresse du fichier en premier paramètre, et son extension en second paramètre. Ce second paramètre est nécessaire car le fichier à traiter est typiquement un fichier temporaire qui ne possède pas d'extension.
La configuration minimale consiste à optimiser des images pour le web :

$gd = new ImgGD($fichier_source, $extension);
$gd->export($destination_fichier);
$gd->ressDestroy();

Les fonctions de filigrane et de recadrage sont compatibles entre elles à condition de respecter l'ordre suivant : filigrane(), puis crop(). Les fonctions de redimensionnement redim() et d'export export(), sont indépendantes des fonctions précédentes. En fin de traitement on utilise la méthode ressDestroy() pour libérer les ressources mémoire.
Notez que les fonctions de filigrane et de recadrage (crop) sont persistantes si vous faites plusieurs exportations pour une même instance. Par exemple si vous devez créer deux images de dimensions différentes avec recadrage et application d'un filigrane pour chacune d'entre elles :

$gd = new ImgGD($fichier_source, $extension);
$gd->filigrane($fil_param);
$gd->crop($crop_param);
$gd->redim(300, 250);
$gd->export($destination_fichier_petit_format);
$gd->redim(1800, 900);
$gd->export($destination_fichier_grand_format);
$gd->ressDestroy();

Le fait d'appliquer la fonction de filigrane avant la fonction de recadrage n'est pas intuitif. Cependant la méthode filigrane() de cette classe est conçue pour fonctionner conjointement avec la classe javascript FiligraneABCI.js afin de proposer un ensemble wysiwyg, également compatible avec une fonction de recadrage. Ainsi pour des raisons d'optimisation interne, on doit appliquer le filigrane avant le crop lors de l'utilisation de ces méthodes dans une même instance, sans quoi il ne sera pas bien positionné ou pourra être invisible dans l'éventuel recadrage effectué.
Cela dit, vous pouvez créer deux images de dimensions différentes et n'appliquer le filigrane et le recadrage que pour la plus grande (ou inversement) :

$gd = new ImgGD($fichier_source, $extension);
$gd->redim(300, 250);
$gd->export($destination_fichier_petit_format);
$gd->filigrane($fil_param);
/*
vous pouvez insérer ici la fonction de crop mais pas plus haut dans le bloc
pour créer la petite image, car elle précéderait la fonction de filigrane.
*/
$gd->crop($crop_param);
$gd->redim(1850, 1000);
$gd->export($destination_fichier_grand_format);
$gd->ressDestroy();

Au besoin vous pouvez utiliser plusieurs instances de la classe ImgGD. Par exemple pour faire un crop sur toutes les images et n'appliquer le filigrane que pour certaines d'entre elles, (ici pour les deux dernières) :

$gd = new ImgGD($fichier_source, $extension);
$gd->crop($crop_param);
$gd->redim(300, 250);
$gd->export($destination_fichier_petit_format);
$gd->ressDestroy();
$gd = new ImgGD($fichier_source, $extension);
$gd->filigrane($fil_param);
$gd->crop($crop_param);
$gd->redim(1850, 1000);
$gd->export($destination_fichier_grand_format);
$gd->redim(1000, 600);
$gd->export($destination_fichier_moyen_format);
$gd->ressDestroy();
/*
N'utilisez cette configuration avec plusieurs instances que si nécessaire, car le
traitement serveur sera plus long (mais le pic de consommation mémoire sera quasi
identique si vous n'ommettez pas d'appliquer "ressDestroy()" à la fin de chaque instance).
Notez que j'ai volontairement créer l'image grand format avant celle moyen format
pour indiquer que l'ordre des éventuels redimensionnements n'a pas d'importance
à l'intérieur d'une même instance.
*/

Consultez le formulaire UploadAjaxABCI_Filigrane_Crop_multiple.php pour avoir un exemple wysiwyg qui permet à l'utilisateur de définir précisément un recadrage et d'appliquer un filigrane personnalisé, y compris pour chaque photo en cas de sélection multiple. Le formulaire UploadAjaxABCI_Filigrane_multiple, plus simple, propose uniquement la fonction de filigrane.

Note : L'initialisation de la classe et les méthodes peuvent renvoyer des erreurs. Il est donc important de les utiliser dans une structure try/catch.

Méthodes de la classe ImgGD

Ces méthodes sont utilisées dans les fichiers de traitement des images. Le fichier d'upload serveur UploadAjaxABCI_Upload_Filigrane_Crop_multiple.php utilise conjointement toutes ces méthodes.

filigrane ($fil_param)
  Applique un filigrane textuel défini par le client en mode wysiwyg, ces données sont donc issues du formulaire. Tous les index doivent être renseignés sans quoi le filigrane ne sera pas créé.
  Important : utiliser la constante __DIR__ pour définir le chemin de la police de caractères utilisée. Des adresses relatives commençant par "../" ne fonctionnent pas.
  $fil_param = [
  'font_dir' => adresse de la police de caractères utilisée
  ,'font_size' => taille de la police
  ,'text' => texte du filigrane
  ,'text_w' => largeur du texte
  ,'text_h' => hauteur du texte
  ,'text_color' => couleur hexadécimale du texte
  ,'text_opacity' => opacité du texte (entre 0 et 100)
  ,'back_on' => 0 ou 1 si un background est appliqué
  ,'back_color' => couleur hexadécimale du background
  ,'back_opacity' => opacité du background (entre 0 et 100)
  ,'back_w' => largeur du background
  ,'back_h' => hauteur du background
  ,'left' => position x du filigrane
  ,'top' => position y du filigrane
  ,'width_preview' => largeur de l'image de prévisualisation
  ,'height_preview' => hauteur de l'image de prévisualisation
  ];
crop ($crop_param)
  Applique un recadrage défini par le client en mode wysiwyg, ces données sont donc issues du formulaire. Toutes les index doivent être renseignés sans quoi le recardrage ne sera pas effectué.
  $crop_param = [
  'width_preview' => largeur de l'image de prévisualisation
  ,'height_preview' => hauteur de l'image de prévisualisation
  ,'width' => largeur de la sélection
  ,'height' => hauteur de la sélection
  ,'x1' => coordonnée x de la sélection
  ,'y1' => coordonnée y de la sélection
  ];
redim ($w_max, $h_max)
  Redimensionne les images proportionnellement en respectant la largeur maximale $w_max et la hauteur maximale $h_max, exprimée en pixels (sans unité).
  - Si $w_max ou $h_max = 0, l'image sera redimensionnée suivant l'unique dimension renseignée.
  - Si $w_max et $h_max = 0, aucun traitement ne sera appliqué.
  - Si l'image fournie est de dimension inférieure aux dimensions maximales indiquées, aucun traitement ne sera appliqué.
export ($image_destination, $quality = 90, $extension = null)
  Exporte l'image créée à l'adresse $image_destination, avec la qualité $quality et au format $extension.
  - $quality est un argument optionnel compris entre 0 et 100, quelque soit le type de l'image. Si vous ne renseignez pas ce paramètre, la qualité sera de 90 ce qui privilégie la qualité du rendu.
  - $extension est un argument optionnel qui permet d'exporter l'image dans un format différent de l'image originelle. Vous pouvez par exemple indiquer "jpg" pour convertir des photos "png" en "jpg" pour créer des fichiers plus petits (au détriment de l'éventuelle transparence des fichiers "png"). Voir le fichier "UploadAjaxABCI_Upload_Traitements_Images.php" pour exemple.
  Si vous ne renseignez pas ce paramètre, les photos seront exportées dans leur format d'origine.
ressDestroy()
  Appliquez cette méthode en fin de traitement pour libérer les ressources mémoire. Elle ne nécessite aucun argument.

### Gestion des erreurs fatales du serveur

Voir exemple d'application dans le fichier "UploadAjaxABCI_Upload_Traitements_Images.php".
Les messages d'erreurs seront concaténés au message configuré dans la classe Javascript avec info.status.errorServer.
Si aucune des deux méthodes catchErrorServer() 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 méthode "catchErrorServer()", notices, warning... A n'utiliser qu'en phase de développement.
catchErrorServer($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'] = ["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->catchErrorServer($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 de la prochaine sélection 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 méthode catchErrorServer(). 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 des 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 (ex: travail sur les images) avec catchErrorServer().
Concernant l'upload lui-même, les erreurs serveur spécifiques à l'upload des fichiers sont gérées automatiquement par la classe d'upload.
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, variable 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.
Utilisez si nécessaire la méthode setChmod() pour définir les droits d'accès.

//...
$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) {

$up->setChmod($destination_fichier,0604)

}
//...

Des exemples dans les fichiers d'upload serveur attribuent des droits 0604. Cela peut varier suivant votre serveur (hébergeur) donc vérifier l'accès des fichiers en production sur le serveur distant pour être certain de la bonne configuration.

### Classe d'upload pour navigateurs obsolètes

La classe UploadFormABCIServeur peut être utilisée pour les navigateurs obsolètes.
Note: Cette classe est compatible php 8.0 mais elle ne sera plus maintenue, de même que les exemples de forumlaires correspondants. Les navigateurs obsolètes inférieurs à IE10 pour lesquels ils ont été initialement concus ayant disparus du paysage informatique.
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 méthode é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 :

- UploadAjaxABCI_Basique_CompNavObs.php
- UploadAjaxABCI_Redimensions_CompNavObs.php
- UploadAjaxABCI_Inscription_Photo_CompNavObs.php

#### 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 "catchErrorServer" 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".

#### Fonctions de la classe "UploadFormABCIServeur"

catchErrorServer ($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 fonction 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".

Fonctions implémentées par le trait UploadABCITraitServices

Idem que pour la classe UploadAjaxABCIServeur

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

propriété | contenu
--- | ---
name | nom du fichier
tmp_name | adresse du fichier temporaire
size | taille du fichier
type | type du fichier
error | message d'erreur si une erreur spécifique au fichier est intervenue
ok | null par défaut (à renseigner par le script)
clean_name | disponible uniquement si aucune erreur n'est intervenue, renseigné avec le nom du fichier nettoyé soit : cleanFileName('name')
destination | disponible uniquement si aucune erreur n'est intervenue, destination avec le nom du fichier nettoyé soit : $dossier_destination.cleanFileName('name')

Contenu du tableau des résultats :

propriété | contenu
--- | ---
Files | Objet tableau des objets spécifiques aux fichiers (cf. ci-dessus)
Error_server | Erreur serveur renseignée par la classe d'upload si dépassement des configurations serveur "post_max_size" ou "max_file_uploads" ou si erreur de vérification du token ou 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_server | Proprié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, notes

### Tests en local

Pour faire des tests sur un serveur local il est conseillé de ne pas diminuer la valeur du paramètre javascript 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 des formulaires 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 :

spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.php';});
<script src="Javascript/jquery.js"></script>'
<script src="Javascript/UploadAjaxABCI.js"></script>
var destination_ajax_upload = 'Php_Upload/UploadAjaxABCI_Upload_Custom_VerifFileExist.php';
var destination_ajax_verif_file = 'Php_Upload/UploadAjaxABCI_VerifFileExist.php';
par :
spl_autoload_register(function ($class) {if(file_exists('Upload-Ajax-ABCI/Php_Upload/Classes/' . $class . '.php')) require 'Upload-Ajax-ABCI/Php_Upload/Classes/' . $class . '.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_Upload_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 :
spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.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_Upload_Inscription_Photo_Crop.php';
par :
spl_autoload_register(function ($class) {if(file_exists('Upload-Ajax-ABCI/Php_Upload/Classes/' . $class . '.php')) require 'Upload-Ajax-ABCI/Php_Upload/Classes/' . $class . '.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_Upload_Inscription_Photo_Crop.php';
ce qui aboutirait à une structure finale de ce type :

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_Upload_Custom_VerifFileExist.php
et
UploadAjaxABCI_Upload_Inscription_Photo_Crop.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 :

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 en production ou si vous utiliser du code complémentaire non compatible avec ce mode.

### Technique d'upload, maintenance

Upload les fichiers par fragments compilés dans un fichier temporaire quand ils dépassent la variable nommée $UpAbci_fragmentSize dans les exemples de formulaires, 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
Le dossier temporaire "Upload_Temp", est protégé par un fichier .htaccess avec la mention "deny from all" de sorte que seul Php puisse y accéder. Les fichiers temporaires n'ont pas d'extension et leur nom est créé par le hash d'un identifiant unique (différent de "id_fich" évoqué plus loin).

#### Nettoyage du dossier des fichiers temporaires

La classe NettoyageTemp, inclue dans le dossier Php_Upload/Classes, permet de nettoyer les fichiers abandonnés dans le dossier temporaire, par exemple suite à une panne internet ou à un arrêt volontaire durant l'upload, non suivi d'une re-soumission du même fichier pour le compléter. Ces cas de figure sont relativement rares en condition normale d'utilisation, et ne concernent pratiquement que l'upload de gros fichiers. Cependant ces fragments de fichiers pourraient s'accumuler au fil du temps et encombrer inutilement votre serveur.
Cette classe dispose de deux méthodes : "nettoyage()" pour un nettoyage direct, et "interval()" pour un nettoyage à interval régulier. Ces méthodes retournent "true" si le processus s'est bien passé.

NettoyageTemp::nettoyage (string $dir_upload_temp = null, int $cookie_duration = null);
NettoyageTemp::interval (int $interval = 86400, string $dir_upload_temp = null, int $cookie_duration = null);

"$dir_upload_temp" représente le chemin relatif du dossier d'upload temporaire par rapport au dossier "Php_Upload".
"$interval" et "$cookie_duration" sont exprimés en secondes.
Si les arguments "$dir_upload_temp" ou "$cookie_duration" ne sont pas renseignés, la classe utilise les valeurs correspondantes du trait "ParamsDefautServeur".
La fonction NettoyageTemp::interval() est intégrée dans tous les scripts côté formulaire depuis la version 7.6b.
Notez que vous devrez renseigner les arguments de ces fonctions si vous configurez votre classe serveur "UploadAjaxABCIServeur" en indiquant des valeurs différentes (pour le dossier temporaire ou la durée de vie du cookie) que celles indiquées dans le trait "ParamsDefautServeur".
La méthode "nettoyage()" est destinée plus particulièrement à être appelée par une tâche programmée car il serait superflu d'appeler trop souvent la fonction de nettoyage qui liste tous les fichiers du répertoire temporaire pour effacer ceux dont la date de création est antérieure à la durée de vie du cookie de sauvegarde. Voir les commentaires en bas du fichier NettoyageTemp.php si vous voulez appeler directement ce fichier par une tâche programmée (ex cron).

### 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 est égal à l'identifiant enregistré dans la propriété id_fich des objets passés en paramètre dans les fonctions événementielles.

id_fich est composé de la concaténation de l'identifiant du formulaire, du nom du champ de type file (1), ainsi que du nom et de la taille du fichier. Et l'ensemble est hashé.

Cet identifiant 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. Ainsi 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 ensuite depuis la seconde. Pour éviter ce problème, on peut définir une adresse unique pour le site, 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 l'identifiant id_fich du fichier. 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. Suivant les cas, le message d'erreur sera différent, voir le paragraphe "Reprise d'upload impossible" ci-desous.
Cela dit, même si config.BackupFormDependency = true le même problème se produira si l'on ouvre le même formulaire dans différents onglets pour télécharger simultanément le même fichier. Dans ce cas de figure on pourrait éventuellement, pour chaque affichage du formulaire, créer dynamiquement un identifiant unique pour le formulaire, mais cela interdirait toute reprise d'upload dès que le visiteur quitte ou rafraichi sa page.
Notez que ces conflits éventuels ne concernent principalement que les gros fichiers qui créent des sauvegardes temporaires durant leur téléchargement. Les plus petits seront téléchargés suffisamment rapidement pour rendre la manoeuvre impossible.
Attention : Ne configurez pas cette option à false si vous avez plusieurs champs de type file dans le même formulaire car cela pourra produire des dysfonctionnements, notamment la classe UpAbci_inputInfosFileUnic sera inopérante pour distinguer un même fichier qui pourrait être chargé depuis des champs différents.
Note : Etant donné que l'identifiant "id_fich" est enregistré dans un cookie, il n'y aura pas de conflit entre différents utilisateurs ou différents navigateurs. D'autre part, le fichier temporaire lié à "id-fich" est créé à partir d'un identifiant aléatoire unique.

#### Reprise d'upload impossible

Ce problème peut parfois survenir en cas de reprise d'upolad suite à l'arrêt volontaire d'un fichier en cours d'upload (avec le bouton stop), ou suite à une panne internet, quand le script php n'a pas eu le temps de terminer correctement son travail. Malgré des fonctions mises en oeuvre dans les scripts Javascript et Php, il est difficile actuellement de supprimer totalement ce problème qui se produit environ 1 fois sur 10 avec des gros fragments (ex $UpAbci_fragmentSize = 256Mo), moins souvent avec de plus petits fragments et apparemment moins souvent également sur un serveur de production.
Je n'ai pas poussé les investigations plus loin, car il est très rare qu'un utilisateur stoppe volontairement la soumission d'un fichier en cours d'upload dans l'intention de la reprendre plus tard. Et en cas de panne internet, la sauvegarde est utilisable dans la très grande majorité des cas.
Un message "Reprise d'upload impossible, sauvegarde non valide..." sera renvoyé en cas de problème dès la reprise de l'upload, ou sinon le fichier sera rejeté à la fin de l'upload par la fonction qui contrôle l'intégrité du fichier et un message correspondant sera renvoyé. Alternatvement cela peut aussi générer un message d'erreur de dépassement de la taille maximale autorisée si vous avez configuré cette option.

#### Taille maximale des fichiers

Il n'y a pas de limite à la taille des fichiers, exceptées celles définies par vous-même.
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 (plusieurs heures de chargement en continu). Cela permet toutefois d'envoyer dans les 300 à 500 Mo en une seule passe (avec une connexion lente) 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 mais uniquement si la détection du type MIME est désactivée côté serveur, sinon le dossier temporaire de la classe d'upload est utilisé pour lire les informations effectivement enregistrées sur le serveur.
b/ Si le fichier est en plusieurs morceaux (UpAbci_blobSlice == 1) ou si la vérification du type MIME est activée, le fichier ou le fragment de fichier est enregistré dans $dossier_temporaire. Si le fichier n'est pas complet, 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 surpasser les limites serveur ainsi que 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_resultat | avec comme valeurs 'continu' ou 'upload_ok' à usage interne suivant que le fichier est terminé ou non.
upabci_ok | contenant 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_erreur | contenant 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_server | un 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_server | 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'envoie rien dans le html. Vous exploiterez ces données comme bon vous semble.
upabci_stop_form | avec 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 traitement du 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 n°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 d'exemple 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, sans raison apparente, vous obtenez le message :

"Reprise d'upload impossible. La sauvegarde n'est pas valide. Recharger votre fichier."

ou

"Erreurs dans la vérification de l'intégrité du fichier."

ou un message inapproprié de dépassement de la taille du fichier, il est possible que vous ayez téléchargé le même gros fichier depuis le même formulaire dans des onglets différents, voir ce paragraphe. Alternativement, cette erreur peut parfois se produire en cas de reprise d'upolad suite à l'arrêt volontaire d'un fichier en cours d'upload (avec le bouton stop), ou suite à une panne internet, voir ce paragraphe.
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();
spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.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.
5/ Affichage des vignettes de prévisualisation des images :
IE 10 ne supporte pas la prévisualisation des images de type png.
6/ Tests de très gros fichiers avec la console du navigateur ouverte :
Le téléchargement de gros fichiers nécessite de nombreuses requêtes (en fonction de la configuration de la taille des fragments). Après de nombreux tests et si vous avez par exemple 4 Mo de mémoire vive sur sotre système, l'enregistrement des requêtes par la console peut saturer votre mémoire. Dans ce cas, le téléchargement s'arrêtera et reverra un message d'erreur non documenté. Parfois le navigateur vous prévient qu'il sature la mémoire, mais pas toujours en temps voulu. Fermez la console du navigateur.
7/ Lenteur pour l'upload des très gros fichiers :
Configurez la taille des fragments au maximum de la capacité de votre serveur pour réduire le nombre de requêtes si votre formulaire est destiné à l'upload de très gros fichiers.
Accessoirement, vous pouvez aussi diminuer la valeur de la configuration javascript config.ajaxTimeOut en ayant lu les précautions d'usage (mais cela n'aura qu'un impact très limité).
8/ Bug récurrent sur l'upload des petits ou gros fichiers :
Dans de rares cas, certains serveurs d'évaluation ou configurations locales provoquent des bugs. Si vous constatez un bug non répertorié dans les points précédents, commencez par tester le script sur un serveur distant professionnel (type Ovh, Gandi, etc.) pour être certain que l'erreur ne provient pas de votre configuration locale.
Ces bugs ont parfois été rapportés lors de l'utilisation de serveurs portables (clé USB) ou dans le contexte d'utilisation d'un framework mais ce problème disparaît en condition d'utilisation réelle sur un serveur distant.
Si le bug apparait uniquement pour l'upload de gros fichiers, il est possible que le cookie envoyé par Php ne puisse pas être récupéré par Javascript. Vérifiez la configuration du cookie dans le fichier Php ParamsDefautServeur ou dans l'initialisation de la classe serveur Php.

### Forum de discussion, liens

Lien de téléchargement du module d'upload
Forum de discussion
imgareaselect Plugin jQuery de Crop - Recadrage
exif-js Librairie 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 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_Upload_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 second paramètre lors de l'initialisation de la classe JavaScript. Alternativement ce paramètre peut ê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 leur appliquant des classes prédéfinies 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 status 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 status 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();

    // Charge la classe de services php pour les fonctions "returnOctets" et  "getUniqid"

    spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.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 dans la super globale $_POST. La notation tableau est également acceptée.
Pour ajouter des champs de saisie spécifiques à chaque fichier, voir ce paragraphe.

### 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 méthode 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_Upload_Basique.php';

    // Initialisation de la classe JavaScript (destination ajax, identifiant formulaire, identifiant réponse)

    var up = new UploadAjaxABCI(destination_ajax, '#form_base', '#reponse_upload');

    /* configuration optionnelle. Par exemple pour limiter les fichiers à une taille de 100Mo :

    up.config.fileSizeMax = '100 Mo';

    */

    // Démarrage DOM chargé

    $(function(){up.Start()});

    </script>

### Récapitulatif de la page complète du formulaire

    <?php

    session_start();

    spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.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_Upload_Basique.php';

    var up = new UploadAjaxABCI(destination_ajax, '#form_base', '#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_Upload_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, une petite dizaine de lignes génériques suffisent :

- Définition du dossier de destination
- Ouverture d'une session
- Chargement des classes serveur
- Initialisation de la classe serveur d'upload en passant le dossier de destination
- Récupération du jeton de sécurité du formulaire
- Vérification de la validité du jeton de sécurité enregistré dans la variable de session
- Et envoi d'un message si la vérification échoue
- Initialisation de l'upload
- Initialisation du transfert du fichier vers son emplacement définitif
- Retour des informations pour la requête ajax

    <?php

    // Vous devez vérifier l'existence du dossier ou changer cette adresse

    $dossier_destination = '../Destination_Upload1/';

    session_start();

    // 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();

    ?>

Notes :
Dans les fichiers d'exemples fournis dans le dossier d'upload, le message "Jeton de sécurité non valide" est remplacé par un message plus complet avec :
$up->exitStatusErreur(SetMessages::get('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 une traduction à proposer suivant la langue du visiteur.
Iimportant : un contrôle complémentaire sur les extensions des fichiers autorisés est indispensable si votre script est destiné à un usage public, cf. sécurité et validité des fichiers uploadés

### 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 méthode é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é infosFile renvoie le contexte html spécifique au fichier (soit le bloc ayant la classe "UpAbci_infosFile").
La propriété fichier sera utilisée pour instancier la librairie EXIF et la propriété infosFile sera utilisée pour afficher certaines informations Exif dans le formulaire.

    up.config.func_FileSelectEach = function(e,obj)

    {

    	// On récupère le fichier avec la propriété "fichier" de l'objet pour initialiser la librairie EXIF (https://github.com/exif-js/exif-js)

    	EXIF.getData(obj.fichier, function() {

    		// Décommenter la ligne ci-dessous pour voir toutes les informations disponibles

    		//console.log(EXIF.getAllTags(this));

    		// Pour l'exemple, affichage des informations dans l'élément html ayant la classe "photo_exif". La propriété "infosFile" de l'objet fait référence au bloc html ayant la classe "UpAbci_infosFile"

    		var destination_html = obj.infosFile.find('.photo_exif');

    		// Si les informations exif existent

    		if(!$.isEmptyObject(EXIF.getAllTags(this)))

    		{

    			// Affichage des informations dans le html

    			destination_html.html("marque : "+EXIF.getTag(this, "Make")+"<br>modèle : "+EXIF.getTag(this, "Model")+"<br>programme d'exposition : "+EXIF.getTag(this, "ExposureProgram")+"<br>date : "+EXIF.getTag(this, "DateTime"));

    		}

    		else

    		{

    			destination_html.html("Aucune information Exif pour cette photo");

    		}

        });

    }

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();

    spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.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 la librairie EXIF" -->

    <script src="Javascript/Exif.js"></script>

    <script src="Javascript/UploadAjaxABCI.js"></script>

    <script>

    var destination_ajax = 'Php_Upload/UploadAjaxABCI_Upload_Basique.php';

    var up = new UploadAjaxABCI(destination_ajax, '#form_base', '#reponse_upload');

    // Extensions autorisées

    up.config.filesExtensions = ['jpg','jpeg','png','gif','tiff'];

    // Initialisation de la librairie EXIF et affichage d'informations dans le html

    up.config.func_FileSelectEach = function(e,obj)

    {

    	// On récupère le fichier avec la propriété "fichier" de l'objet pour initialiser la librairie EXIF

    	EXIF.getData(obj.fichier, function() {

    		// Pour l'exemple, affichage des informations dans l'élément html ayant la classe "photo_exif". La propriété "infosFile" de l'objet fait référence au bloc html ayant la classe "UpAbci_infosFile"

    		var destination_html = obj.infosFile.find('.photo_exif');

    		// Si les informations exif existent

    		if(!$.isEmptyObject(EXIF.getAllTags(this)))

    		{

    			// Affichage des informations dans le html

    			destination_html.html("marque : "+EXIF.getTag(this, "Make")+"<br>modèle : "+EXIF.getTag(this, "Model")+"<br>programme d'exposition : "+EXIF.getTag(this, "ExposureProgram")+"<br>date : "+EXIF.getTag(this, "DateTime"));

    		}

    		else

    		{

    			destination_html.html("Aucune information Exif pour cette photo");

    		}

        });

    }

    $(function(){up.Start()});

    </script>

    </html>

Notes :
- Le fichier d'exemple UploadAjaxABCI_Infos_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 status "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 méthode 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;

    	var Max_index = Type.length - 1;

    	while(Bits >= 1000 && Index < Max_index)

    	{

    		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 = Index < 3 ?  Bits.toFixed(1) : Bits.toFixed(3);

    	return(Bits+''+Type[Index]+'b/s');

    }

    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é "infosFile" 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.infosFile.find(".vitesse").html(BitFormate(bit_upload/time_upload));

    	}

    }

Récapitulatif de la page :

    <?php

    session_start();

    spl_autoload_register(function ($class) {if(file_exists('Php_Upload/Classes/' . $class . '.php')) require 'Php_Upload/Classes/' . $class . '.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 status "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_Upload_Basique.php';

    var up = new UploadAjaxABCI(destination_ajax, '#form_base', '#reponse_upload');

    var BitFormate = function (Bits)

    {

    	var Type = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"];

    	var Index = 0;

    	var Max_index = Type.length - 1;

    	while(Bits >= 1000 && Index < Max_index)

    	{

    		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 = Index < 3 ?  Bits.toFixed(1) : Bits.toFixed(3);

    	return(Bits+''+Type[Index]+'b/s');

    }

    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é "infosFile" 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.infosFile.find(".vitesse").html(BitFormate(bit_upload/time_upload));

    	}

    }

    $(function(){up.Start()});

    </script>

    </html>

### Conclusion

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, création de filigrane, création d'album photo, validation de formulaire, notation des fichiers, etc. consultez les autres exemples fournis et les commentaires dans le code source de ces fichiers.