Upload de fichiers Ajax/Html5/jQuery

UploadAjaxABCI v7.0

Copyright (c) 20014-2018 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
  • Exemples fonctionnels et prêts à l'emploi avec classes Php fournies côté serveur

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

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

Installation

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

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

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

Conseils d'utilisation

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

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

Vous constaterez avec le tutoriel et ce premier exemple que l'on peut obtenir un formulaire complet 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. Cependant quelques lignes suffisent pour un upload classique qui bénéficiera de toutes les fonctionnalités énoncées plus haut.

Deux fichiers complètent le tutoriel et donnent une vue plus détaillée des possibilités d'interaction client-serveur :
- 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 regroupe les possibilités d'échange de données entre client et serveur et des exemples d'utilisation des fonctions javascript événementielles.

Consultez les fichiers ci-dessus, 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é.

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

Code couleur utilisé dans ce mode d'emploi :
Code HTML : classes prédéfinies permettant d'afficher des informations,
et attributs data-upabcicss-* permettant de définir des styles événementiels
Code JAVASCRIPT : paramètres de la classe Javascript,
et fonctions Javascript événementielles
Code PHP
Informations complémentaires
Astuce : cliquez sur les boutons "+" dans le menu du mode d'emploi pour permettre d'afficher le contenu de plusieurs rubriques simultanément.

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 d'ordre général (c.f. Tutoriel et code source des fichiers d'exemples).

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 (à définir selon vos besoins) et qui seront appliqués en fonction des différentes étapes du traitement des fichiers et du formulaire.

3/ Fonctions Javascript événementielles

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

4/ Exemple

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

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

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

tandis que :

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

affichera le temps restant estimé.

A la fin de l'upload du fichier, l'affichage du temps restant ne sera plus utile. Je pourrais le laisser en place avec la valeur 0 mais si je veux épurer le résultat pour ne garder que les informations utiles, je peux supprimer cet affichage en utilisant le style css événementiel "data-upabcicss-result" qui sera activé dès la fin de traitement du fichier. Le code html 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 conplément des informations EXIF citées plus haut, je donne plusieurs exemples de Crop + Upload qui utilisent le plugin "ImgAreaSelect".

Fichiers d'exemples

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

  • Configuration de base
    UploadAjaxABCI_Basique.php

    Principe de base et styles css événementiels.

  • Des exemples progressifs plus complets
    UploadAjaxABCI.php

    Exemples de configurations et styles css événementiels.
    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énemntielles et retours serveur.
    UploadAjaxABCI_Champs_Sup_Notation.php

    Système de notation avec 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.

  • Redimensionnements d'images
    UploadAjaxABCI_Redimensions.php

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

  • Crop d'images multiples
    UploadAjaxABCI_Crop_multiple.php

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

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

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

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

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

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

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

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

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

Configuration côté formulaire

Script serveur qui alimente le formulaire

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

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

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

Configuration du formulaire

1/ 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. remarque dans le 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 d'autres 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 correpondant 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 indique 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

Toutes ces classes prédéfinies 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

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

2/ Informations spécifiques à chaque fichier

ClasseConteneur des informations sur les fichiers
UpAbci_infosFileBloc indispensable pour l'affichage des informations spécifiques à chaque fichier.
Doit être inclus dans le bloc défini en troisième paramètre lors de l'initialisation de la classe Javascript. En cas d'upload multiple, ce bloc est dupliqué, en conséquence ne pas utiliser d'id à l'intérieur de ce bloc.
Important : Les classes ci-dessous doivent être inclues dans le bloc html ayant la classe UpAbci_infosFile.
ClasseInformation / comportement
UpAbci_nameNom du fichier
UpAbci_sizeTaille du fichier
UpAbci_progressionGProgression graphique dans une balise html <progress>
UpAbci_progressionTProgression textuelle
UpAbci_percentagePourcentage effectué
UpAbci_backupSauvegarde effectuée (0 si upload terminé ok)
UpAbci_durationTemps passé
UpAbci_remainingTimeTemps restant
UpAbci_statusStatus en cours, ok, arrêt, erreur, éventuellement complété côté serveur
UpAbci_imgPreviewAffiche l'aperçu si c'est une image dans la limite des configurations Javascript "config.imgPreviewMaxSize" et "config.imgPreviewMaxSizeTotal". Voir l'option de configuration "config.imgPreviewUseFileReader" en cas de bug aléatoire sur Firefox
UpAbci_inputFileNameAffiche le nom de l'input de type file
UpAbci_stopComportement onclick : Arrêt de l'upload du fichier
UpAbci_inputInfosFileUnicComportement : 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 fonction 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. Ce n'est pas le cas d'un bouton de type radio par exemple qui ne permet qu'une sélection pour tous les inputs de même nom dans le formulaire, ce qui est incompatible avec des sélections différentes dans un upload multiple, 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.

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

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

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

2/ Styles applicables localement

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

3/ Ordre d'application des styles *

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

* 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" (entre autres) n'aient été appliqués préalablement.

4/ Styles configurables en Javascript

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

Configuration de la classe Javascript UploadAjaxABCI

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

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

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

// ...

// Démarrage, DOM chargé
$(function(){MyUpload.Start()});
param1 : 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
note : Le contenu du bloc conteneur défini par le troisième paramètre sera réinitialisé à chaque sélection de fichiers.

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, utiliser la fonction Start() pour lancer le script, DOM chargé
$(function(){up.Start()});


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

Options de configuration Javascript

Liste des paramètres configurables

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

Les 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 = 500
En milliseconde (sans unités), délai d'envoi de la requête Ajax, utile pour éviter de saturer un serveur local poussif. Evitez de mettre cette valeur à zéro. Je ne pourrai pas être tenu pour responsable si une sollicitation importante du système donne le coup de grâce d'un disque dur en cours d'agonie.
config.filesExtensions = []
Tableau des extensions autorisées (les variantes majuscules/minuscules sont automatiquement prises en compte). Si le tableau est vide aucune vérification n'est faite. Faire un contrôle supplémentaire côté serveur par sécurité (pas obligatoire mais très vivement conseillé).
config.filesExtensionsInput = []
Tableau des extensions autorisées pour chaque input du formulaire (les variantes majuscules/minuscules sont automatiquement prises en compte). La configuration requière le nom de l'input comme index. Par exemple si le champ se nomme "file1", la configuration pourra être : config.filesExtensionsInput["file1"] = ['jpeg','jpg','png']. Cette option peut être utile si plusieurs champs de type file sont inclus dans le même formulaire.
config.fileSizeMax = null
Taille maximale du fichier utilisateur. Si = 0 ou null aucune vérification n'est faite sur la taille du fichier. Accepte un nombre en octets ou une chaîne de caractère formatée avec les unités. Les espaces et la lettre "o" sont optionnels et le formatage ne tient pas compte de la casse. Par exemple 1073741824 = '1073741824o' = '1024Mo' = '1024 M' = '1048576k' = '1048576 Ko' = '1 go' = '1 G' (les nombres décimaux sont acceptés). Faire un contrôle supplémentaire côté serveur par sécurité (pas obligatoire mais très vivement conseillé).
config.customFileSelect = null
Un id ou une class ex "#mon_bouton" ou ".mon_bouton" pour identifier un bouton personnalisé de sélection de fichier. Ce bouton (ou ce lien) doit se situer à l'intérieur du formulaire indiqué en 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. 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.
config.cssSubmitOn = null
Styles avec notation standard (ex : "background:#ccc;border:1px solid blue;...") qui seront appliqués durant le traitement du formulaire sur les boutons de type "submit" inclus dans le formulaire. Les styles initiaux (initialement définis dans le html) seront restitués une fois le traitement terminé.
config.cssFileSelectOn = null
Styles avec notation standard (ex : "background:#ccc;border:1px solid blue;...") qui seront appliqués durant le traitement du formulaire sur les boutons de type "file" OU les boutons défini par "config.customFileSelect" inclus dans le formulaire. Les styles initiaux (initialement définis dans le html) seront restitués une fois le traitement terminé.
config.imgPreviewStartAuto = true
Booléen true ou false. true pour un affichage immédiat des vignettes images (si les contrôles sur le poids des images pour prévisualisation sont respectés). Si false vous pouvez utiliser la fonction "func_ImgPreviewStartAll()" pour faire afficher les vignettes dans le formulaire au moment voulu (voir le fichier d'exemple UploadAjaxABCI_Custom.php et les fichiers de Crop).
config.imgPreviewMaxSize = null
En Mo (sans unités). Poids maximal de chaque image pour prévisualisation. Si null, aucun contrôle individuel n'est fait avant la prévisualisation mais vous pouvez néanmoins contrôler le poids total de l'ensemble des images avec la configuration "config.imgPreviewMaxSizeTotal".
config.imgPreviewMaxSizeCancelAll = false
true ou false. Si true et que "config.imgPreviewMaxSize" est dépassé pour au moins une image, aucune vignette ne sera affichée.
config.imgPreviewMaxSizeTotal = null
En Mo (sans unités). Poids total maximal de toutes les images pour prévisualisation. Si dépassé aucune vignette ne sera affichée. Si null, le contrôle n'est pas fait. Les images dépassant "config.imgPreviewMaxSize" ne sont pas totalisées puisqu'elles ne sont pas affichées. Par ailleurs, "config.imgPreviewMaxSizeCancelAll" à la priorité sur ce contrôle.
config.imgPreviewMaxWidth = 90
En pixels (sans unités), largeur maximale de l'aperçu image. 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 produit parfois des bugs aléatoires sous Firefox qui n'affiche pas entièrement certaines images (indépendamment des images elles-mêmes qui pourront s'afficher correctement dès la prochaine sélection). En attendant la réparation de ce bug par l'équipe Mozilla cf https://bugzilla.mozilla.org/show_bug.cgi?id=1434496, vous pouvez configurer cette option à true spécifiquement pour firefox afin de garantir un bon affichage des vignettes en toute circonstance, par exemple si vous proposez des outils de recadrage avant upload. Voir les fichiers exemples de crop.
config.infosRefresh = 1
En seconde (sans unités), fréquence de rafraîchissement des informations textuelles.
config.remainingTimeCompute = 10
En seconde, temps de calcul avant l'affichage du temps restant estimé. Si trop court le résultat n'est pas significatif. Durant l'attente c'est le paramètre "info.remainingTimeComputeWaiting" qui s'affiche. A l'issue de cette période, 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 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 fonction événementielle "config.func_FormEnd(tableau)".
config.queryFormEnd = false
Booléen true ou false. Si = true, une requête additionnelle est envoyée au serveur pour indiquer la fin de traitement du formulaire avec comme paramètre un tableau d'information sur chaque fichier sélectionné (excepté si config.submitWithoutFile = false et qu'aucun fichier n'a été soumis). Si l'option est égale à true et config.submitWithoutFile = true et qu'aucun fichier n'est soumis un tableau restreint est renvoyé directement dans l'unique requête adressée au serveur.
config.BackupFormDependency = true
Booléen true ou false. "true" lie les possibilités de reprise d'upload du fichier à l'identifiant du formulaire et au nom du champ de type file. Voir cette note avant de modifier la valeur de cette option.
config.cookiePath = '/'
Path du cookie.
config.fragmentSize = 4194304
Taille du fragment en octet (sans unités) si le script ne trouve pas de champ nommé "UpAbci_fragmentSize" (défini avec une valeur non nulle et supérieure à 1048576) dans le formulaire. Si une valeur valide est trouvée dans le formulaire alors config.fragmentSize sera égal à cette valeur moins 10240. 10240 étant le nombre d'octets que prend arbitrairement la classe comme marge de sécurité pour que le post total (files + données textuelles) ne soit pas supérieur à la config Php "post_max_size" dans le cas où l'on choisirait une valeur de fragment égale à "post_max_size".
config.browserOutdeted = 'Navigateur obsolète incompatible'
Message pour les navigateurs incompatibles.
- Si non vide et différent de null, ce message s'affichera à la sélection des fichiers et à la soumission du formulaire en cas de navigateur obsolète. Le code javascript de la classe ne sera pas exécuté - excepté celui éventuellement défini par la fonction événementielle "config.func_BrowserOutdeted()" - et le formulaire ne sera pas envoyé.
- Si config.browserOutdeted = null, aucun message ne sera affiché en cas de navigateur obsolète. Le code javascript de la classe ne sera pas exécuté - excepté celui éventuellement défini par la fonction événementielle "config.func_BrowserOutdeted" - et le formulaire sera envoyé par défaut à l'adresse définie dans l'attribut "action" du formulaire.
config.serverFatalErrorDisplay = true
Concatène les messages renvoyés par les erreurs fatales du serveur aux status Javascript "info.status.errorServer" et "info.queryEndErrorServer" (défini plus bas). Les messages renvoyés dépendent du script côté serveur.
Deux fonctions "cathErrorServeur()" et "setModeDebug()" sont disponibles dans la classe d'upload Php pour gérer le retour des erreurs fatales (cf fichiers exemples de redimensionnements et de Crop). Vous pouvez laisser true pour les exemples fournis car le script serveur ne renvoie que les messages personnalisés définis avec "cathErrorServeur()". "setModeDebug()" renvoie tout mais ne devrait pas être utilisé en production.
config.uniqidForm = this.SHA1(this.Uniqid('UploadAjaxABCI',true))
Valeur générée à l'affichage du script s'il ne trouve pas de champ nommé "UpAbci_uniqidForm" dans le formulaire. 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 = 'Dépassement de la taille maximale autorisée.'
Message si dépassement de "config.fileSizeMax".
info.status.errorExtension = 'Extension non valide.'
Message si l'extension ne fait pas partie du tableau "config.filesExtensions".
info.status.errorServer = 'Echec du téléchargement.'
Complété automatiquement par l'erreur serveur (si config.serverFatalErrorDisplay = true) ou par une erreur générée par le script Php d'upload.
info.remainingTimeComputeWaiting = 'calcul en cours'
S'affiche durant la période définie par la variable "config.remainingTimeCompute".
info.unitsSpacing = '&nbsp;'
Espacement par défaut entre les valeurs et leurs unités.
info.queryEndErrorServer = 'Echec dans la finalisation du traitement serveur. '
Annonce de fin de traitement du formulaire si config.queryFormEnd = true et erreur serveur lors de cette dernière requête. Complété automatiquement par l'erreur serveur si "config.serverFatalErrorDisplay = true"
Les options ci-dessous définissent l'annonce Javascript pour la reprise de la sauvegarde si "config.recoveryBackupConfirm = true"
info.recoveryBackupConfirm.name = 'Récupération du fichier : '
Annonce Javascript suivie du nom du fichier.
info.recoveryBackupConfirm.size = '\nSauvegarde en cours : '
Annonce (suite) suivie de la taille de la sauvegarde (\n pour retour ligne car la boite de confirmation est en Javascript).
info.recoveryBackupConfirm.message = '\n\nCliquez sur "OK" pour compléter ce fichier ou sur "Annuler" pour réinitialiser le téléchargement.'
Annonce (suite) dernière ligne.
- Remarque : la fonction de prévisualisation des images 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.

- 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 fonction Start() pour lancer le script, DOM chargé
$(function(){up.Start()});

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

Fonctions Javascript événementielles

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

Noter que le déclenchement de cette fonction 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 fonction événementielle "config.func_onFormSubmit()" a été définie (voir plus haut) et est conçue pour être utilisée à l'intérieur de cette fonction. A noter qu'après l'utilisation de "func_SubmitForm()" le paramètre "tableau" envoyé par la fonction "config.func_onFormSubmit(event,tableau)" est réinitialisé (vide).
func_ImgPreviewStartAll
Utilisation : func_ImgPreviewStartAll();
NE DOIT PAS être configurée, mais uniquement utilisée comme commande pour déclencher l'affichage de toutes les images de prévisualisation. Fonctionne uniquement si config.imgPreviewStartAuto = false (voir l'exemple UploadAjaxABCI_Custom.php et les exemples de Crop) sinon la prévisualisation est automatique.
Contenu des objets spécifiques à chaque fichier passés en paramètre dans les fonctions événementielles
propriétécontenu
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.
A noter que "upabciErrorUser" ne comptabilise pas "upabciErrorPreview"
img_widthuniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé)
img_heightuniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé)
img_orientationuniquement si prévisualisation (bloc ".UpAbci_imgPreview" utilisé) et information disponible
img_prev_delayed0 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"
iterationnombre d'itérations de la requête Ajax pour le fichier
join_file (3)Propriété libre (à définir selon vos besoins) spécifique à chaque fichier dont le contenu sera envoyé dans le paramètre "UpAbci_joinFile" de la requête Ajax
upAbci(objets html) tous les objets html d'information de fichier ayant une classe ".Upabci_..."
qte_savequantité sauvegardée en continu, y compris l'éventuelle sauvegarde initiale trouvée à la sélection du fichier
qte_save_inisauvegarde initiale trouvée à la sélection du fichier
qte_uploadquantité en cours
result (4)"ok_done", "backup_done", "error_done", "backup_fail", "error_fail" ou "0_0".
Préfixe = état du fichier, suffixe = état de la requête. "0_0" si pas traité.
stop0 ou 1 (sur demande utilisateur)
stop_all0 ou 1 (sur demande utilisateur)
time_endfin de l'upload en secondes et millisecondes
time_startdébut de l'upload en millisecondes
inputs_infosFilePour 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 fonction é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) Si vous souhaitez annuler la soumission d'un fichier, vous pouvez définir la propriété "fichier.upabciErrorUser" avec une valeur entière supérieure à 0, ex : "fichier.upabciErrorUser = 1". Un exemple est donné dans le code source du fichier UploadAjaxABCI_Custom_VerifFileExist.
(3) Voir paragraphe suivant.
(4) "result" qui indique le résultat final du fichier est renseigné au retour du traitement serveur sinon il vaut "0_0".

Ajout d'informations spécifiques à chaque fichier

Vous aurez parfois besoin de joindre des informations additionnelles spécifiques à chaque fichier 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 crop donnent des exemples d'utilisation de cette propriété.

Fonctions et librairies Javascript annexes

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

- DrawCanvasABCI.js cette classe (prototype) indépendante est disponible pour afficher un système de notation (coeurs ou étoiles) spécifique à chaque fichier et est utilisée dans le fichier d'exemple "UploadAjaxABCI_Champs_Sup_Notation.php".

- EXIF.js cette librairie qui retourne les informations EXIF des appareils photos numériques est utilisé dans l'exemple "UploadAjaxABCI_Infos_Exif.php".

- jquery.imgareaselect-10-0-rc-1.js ce module jQuery qui permet le recadrage des photos est utilisé dans les exemples "UploadAjaxABCI_Crop_multiple.php" et UploadAjaxABCI_Crop_multiple_multiple.php

Code Javascript complémentaire

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

- Si vous souhaitez ajouter des comportements onchange sur les boutons de sélection des fichiers, vous aurez des problèmes en cas de soumissions successives du formulaire sans rafraîchissement de la page. En effet pour compenser un bug IE10, le html du champ de type file est copié, supprimé puis recoller à chaque soumission du formulaire. Etant donné qu'il est impossible de cloner ce champ pour le bon fonctionnement du système, les événements Javascript ne seront pas réinsérés.
Utilisez les fonctions 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...", "...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.5

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

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

Configuration de la classe Php UploadAjaxABCIServeur

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

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

$up = new UploadAjaxABCIServeur($dossier_destination=null, $dossier_temporaire=null, $cookie_heures=null, $cookie_path=null, $verif_filesize_sup2Go=null)
$dossier_destination Dossier de destination de l'upload. Si ce paramètre n'est pas renseigné ou s'il est égal à la constante null, la destination sera celle renseignée dans la classe "ParamsDefautServeur".
$dossier_temporaire Dossier où sont enregistrés les fichiers temporaires.
$cookie_heuresLa durée de vie du cookie de sauvegarde, en heures. Détermine la durée de disponibilité des sauvegardes de fichiers en cas d'upload partiel (arrêt volontaire ou panne internet).
$cookie_pathLe path du cookie envoyé en Php. Doit pouvoir être récupéré par le script en Javascript.
$verif_filesize_sup2GoSuivant les serveurs, le contrôle de la taille d'un fichier supérieur à 2 Go peut retourner un résultat erroné. Pour cette raison, le contrôle de l'intégrité des fichiers qui compare la taille du fichier temporaire avec la taille du fichier originel, n'est pas faite automatiquement pour les fichiers supérieurs 2Go.
Si la fonction Php filesize() - utilisée pour ce contrôle par la classe Php - est efficace sur votre serveur pour des fichiers supérieurs à 2Go, il est recommandé de configurer ce dernier paramètre à true.
Note : L'adresse des dossiers passés en paramètre doit comporter un séparateur final, ex:

$dossier = '../Destination/';

Valeurs par défaut

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

Les paramètres que vous passez dans l'initialisation de la classe "UploadAjaxABCIServeur" seront pris en compte s'ils sont strictement différents de la constante null, c'est à dire qu'une valeur renseignée et vide comme '' sera prise en compte.

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

Récupération des champs du formulaire

Vous pouvez récupérer les valeurs de vos champs input éventuellement ajoutés dans le formulaire 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 en dehors 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 aura pas de confusion avec ceux de même nom associés aux fichiers précédents/suivants et vous pourrez 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 (pour information) :

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

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

Liste des index des tableaux $UpAbci_form et $UpAbci_formEnd :

Dans tous les cas
id_formL'identifiant, id ou classe du formulaire. Retourne une chaine de caracatère de forme "#id" ou ".classe"
uniqid_formL'identifiant unique du formulaire (token)
iteration_formNombre d'itérations de la requête Ajax pour le formulaire (remise à zéro pour chaque nouvelle soumission du formulaire)
Si un fichier
est joint
au formulaire
input_nameNom de l'input de type file
id_fichIdentifiant 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
nameLe nom du fichier
sizeLa taille du fichier
typeLe type du fichier
lastModifiedLa valeur de "lastModified"
qte_saveQuantité sauvegardée en continu
qte_uploadQuantité uploadée en continu
result (1)"ok_done", "backup_done", "error_done", "backup_fail", "error_fail", ou "0_0"
Préfixe = état du fichier, suffixe = état de la requête
time_start Début de l'upload en millisecondes
time_end Fin de l'upload en secondes et millisecondes
iterationNombre 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

Note : aucune méthode 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.

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.

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

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

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

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

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

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 html du fichier. Elles définissent de plus les styles événementiels qui seront appliqués dans le html : data-upabcicss-result, et data-upabcicss-result-ok ou data-upabcicss-result-error suivant la méthode choisie.

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 ("" 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 fonctions 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 erreurs fatales du serveur

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

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

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

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

$tab_erreurs = array();

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

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

$up->cathErrorServeur($tab_erreurs);

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

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

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

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

Note : la gestion 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 avec cathErrorServeur().
Concernant l'upload lui-même et donc si vous ne faites pas de traitement complémentaire, vous ne devriez plus avoir d'erreur une fois le script correctement configuré puisque ce module surpasse les limitations serveurs spécifiques à l'upload avec la fragmentation.

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

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

Visibilité des fichiers uploadés

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

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

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

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

Upload sans Transfert

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

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

Si donc vous ne souhaitez pas utiliser la fonction Transfert() vous pouvez utiliser les méthodes setTransfertOk(), deleteCookieSave() et effacer le fichier temporaire pour réaliser les fonctions équivalentes.

Notez que si vous n'effacez ni le cookie de sauvegarde, ni le fichier temporaire, le visiteur retrouvera la sauvegarde complete dès la prochaine sélection de son fichier et le prochain téléchargement se fera sans avoir à attendre de nouveau puisqu'il pourra utiliser la sauvegarde existante. 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").
$dossier_destination = ''; // ce paramètre ne sera pas utilisé
$dossier_temporaire = '../Upload_Temp/';

//...

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

//...

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

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

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

// ...

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

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

unlink($fichier_complet);

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

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

}

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

Classes Php disponibles

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

- Les classes UploadAjaxABCIServeur et UploadFormABCIServeur héritent de la classe UploadABCIServices.
- Les classes UploadAjaxABCIServeur, NettoyageTemp et C_PDO utilisent la classe (trait) ParamsDefautServeur.
- Les classes SetMessages et Messages sont utilisées un peu partout dans les scripts d'exemples et dans les classes elles-mêmes.

- Les classes C_PDO, CropRedim, RedimImage et CorrectionExifJpg peuvent émettre des erreurs, aussi vous devez les utiliser dans un bloc try/catch (cf. fichiers d'exemples code serveur dans le dossier "Php_Upload").
C_PDO
Classe de connexion BDD.
CropRedim
Classe de Crop et redimensionnement d'images (utilise la bibliothèque GD).
CorrectionExifJpg
Corrige l'orientation des images jpg suivant ses informations EXIF (utilise la bibliothèque GD).
Messages
Classe de centralisation des messages.
NettoyageTemp
Classe de nettoyage du dossier temporaire.
ParamsDefautServeur
Trait incluant les paramétrages par défaut de la classe "UploadAjaxABCIServeur".
RedimImage
Classe de redimensionnement d'images (utilise la bibliothèque GD).
SetMessages
Classe de chargement et de sélection des messages.
UploadABCIServices
Classe de services, fonctions utilitaires communes dans un upload.
UploadAjaxABCIServeur
Classe serveur ajax (détaillée plus haut) liée à la classe javascript "UploadAjaxABCI.js".
UploadFormABCIServeur
Classe serveur pour navigateurs obsolètes (détaillée ci-dessous).
Validateur
Classe de validation des champs d'un formulaire.

Classe d'upload pour navigateurs obsolètes

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

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

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

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

Configuration de la classe "UploadFormABCIServeur"

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

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

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

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

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

Méthodes de la classe "UploadFormABCIServeur"

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

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

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

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

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

Contenu du tableau des résultat :

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

Mise en production

Tests en local

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

Externalisation des scripts et des dossiers d'upload

(à l'usage des débutants)

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

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

arborescence


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

B/ Externalisation des dossiers d'upload

Si maintenant vous souhaitez externaliser les dossiers des fichiers d'upload, rendez-vous dans le dossier Php_Upload et les fichiers de destination Ajax qui chargent les fichiers, soit respectivement pour nos deux fichiers d'exemples :
UploadAjaxABCI_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 :

arborescence


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

C/ Mode "use strict" pour le code Javascript

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

Technique d'upload utilisée, maintenance

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

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

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

Plus de détails

Nettoyage du dossier des fichiers temporaires

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

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

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

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

Notes techniques

Détails sur la sauvegarde

Le script d'upload utilise le fichier temporaire sauvegardé (si disponible) pour compléter le téléchargement, automatiquement dès la sélection du même fichier, ou après demande de confirmation. La durée de disponibilité de la sauvegarde dépend de la durée de vie du cookie envoyé par le script Php d'upload. Le nom du cookie est égal à l'identifiant enregistré dans la propriété id_fich des objets passés en paramètre dans les fonctions événementielles.

Cet identifiant est composé de l'identifiant du formulaire, du nom du champ de type file (1), ainsi que du nom et de la taille du fichier. 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 depuis la seconde adresse lors de sa visite suivante. Pour éviter ce problème, on peut définir une adresse unique par réécriture d'url dans un .haccess.

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

Conditions de reprise d'upload

L'option Javascript config.BackupFormDependency = true lie les possibilités de reprise d'upload des fichiers à l'identifiant (classe ou id) du formulaire ainsi qu'au nom du champ de type file.
Si = false, ces éléments ne sont pas utilisés pour créer 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. Le script renverra alors un message d'erreur en fin d'upload "Fichier temporaire non valide".
Même chose si config.BackupFormDependency = true et que l'on ouvre le même formulaire dans différents onglets pour télécharger simultanément le même fichier.

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 disfonctionnements, notamment la classe UpAbci_inputInfosFileUnic sera inopérante pour distinguer un même fichier qui pourrait être chargé depuis des champs différents.

Taille maximale des fichiers

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

Interactions Javascript/Serveur

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

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

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

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

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

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

Debug

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

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

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

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

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

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

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

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

3/ Si vous obtenez le message :

"Fichier temporaire non valide."

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

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

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

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

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

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

$UpAbci_uniqidForm = $up->getUniqid();

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

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


5/ Affichage des vignettes de prévisualisation des images :
- IE 10 ne supporte pas la prévisualisation des images de type png.
- Firefox produit parfois un bug aléatoire (image partiellement affichée ou non affichée) suivant le nombre ou le poids des images

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 Ajax-jQuery peut donc être utilisé par des débutants sans connaissances en JavaScript tout en bénéficiant des fonctionnalités intégrées.

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

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

Cet exemple est basé sur le formulaire UploadAjaxABCI_Basique.php et sur son script serveur UploadAjaxABCI_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 pourra être un objet jQuery.

Affichage des informations des fichiers

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

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

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

Pour afficher les informations spécifiques à chaque fichier, il suffit de définir des éléments HTML en appliquant des classes réservées à cet effet. Je choisis ici d'utiliser des "span" pour un affichage en ligne, par exemple :
<span class="UpAbci_imgPreview"></span>
affichera une vignette de prévisualisation si le fichier est une image, sinon rien.
<span class="UpAbci_name"></span>
affichera le nom du fichier.
<progress class="UpAbci_progressionG"></progress>
affichera une barre de progression graphique de l'upload.
<span class="UpAbci_status">en attente</span>
affichera le 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();
header('Content-type: text/html; charset=UTF-8');// Inutile avec php >= 5.6

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

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

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

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

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

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

Champs supplémentaires dans le formulaire

Vous pouvez ajouter d'autres champs dans le formulaire, ils seront transmis côté serveur 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 fonction Start().
<script src="Javascript/jquery.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script>
// Destination de la requête ajax d'upload
var destination_ajax = 'Php_Upload/UploadAjaxABCI_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 de la fonction, DOM chargé
$(function(){up.Start()});
</script>

Récapitulatif de la page complète du formulaire

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

<div id="reponse_upload">
<div class="UpAbci_infosFile" style="display:none;" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span>
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
<span class="UpAbci_stop" style="color:red">stop</span>
</div>
</div>
</form>
</body>
<script src="Javascript/jquery.js"></script>
<script src="Javascript/UploadAjaxABCI.js"></script>
<script>
var destination_ajax = 'Php_Upload/UploadAjaxABCI_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, 10 lignes génériques suffisent :
<?php
// Vous devez vérifier l'existence du dossier ou changer cette adresse
$dossier_destination = '../Destination_Upload1/';

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

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

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

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

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

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

$up->Transfert();

// INDISPENSABLE en fin de script, "exitReponseAjax()" retourne les informations nécessaires pour la requête ajax.
$up->exitReponseAjax();
?>
A noter que dans le fichier d'exemple fourni dans le dossier, le message "Jeton de sécurité non valide" est remplacé par un message plus complet avec :
$up->exitStatusErreur(SetMessages::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.

Fonctions JavaScript événementielles

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

Ci-dessous, un exemple pour afficher les informations Exif des fichiers jpg/jpeg et tiff qui sont enregistrées dans les images des appareils photo numériques. J'utilise ici la fonction événementielle config.func_FileSelectEach qui sera exécutée à la sélection de chaque fichier en exploitant les paramètres disponibles dans la fonction.
config.func_FileSelectEach = function(e,obj) {}
Le paramètre e retourne l'objet event et le paramètre obj retourne un objet contenant de nombreuses propriétés. Notamment la propriété fichier renvoie le fichier en cours et la propriété 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();
require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();
$UpAbci_fragmentSize = $up->returnOctets('2M');
$UpAbci_uniqidForm = $up->getUniqid();
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Basique Upload Ajax ABCIWEB</title>
</head>
<body>
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" multiple="multiple" />
<input type="hidden" value="<?=$UpAbci_fragmentSize?>" name="UpAbci_fragmentSize" />
<input type="hidden" value="<?=$UpAbci_uniqidForm?>" name="UpAbci_uniqidForm" />
<input type="submit" value="Envoyer" />

<div id="reponse_upload">
<div class="UpAbci_infosFile" style="display:none;" data-upabcicss-select-file="display:block;">
<p>
<span class="UpAbci_imgPreview" style="float:left"></span>
<span class="photo_exif"></span>
</p>
<p style="clear:both">
<span class="UpAbci_name"></span>
<progress class="UpAbci_progressionG"></progress>
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
<span class="UpAbci_stop" style="color:red">stop</span>
</p>
</div>
</div>
</form>
</body>
<script src="Javascript/jquery.js"></script>
<!-- charge 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 fonction javascript événementielle config.func_FileInProgressEach qui est appelée lors de la progression des fichiers (à une fréquence définie par l'option de configuration javascript "config.infosRefresh" soit actuellement chaque seconde). J'utilise le paramètre obj de la fonction pour récupérer les informations nécessaires et faire afficher la vitesse de l'upload.

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

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

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

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

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

// Cela ne devrait pas arriver mais je vérifie par sécurité que time_upload soit supérieur à 0 pour éventuellement éviter une vilaine division par 0.
if(typeof time_upload === "number" && time_upload > 0)
{
// La propriété "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();
require 'Php_Upload/Classes/UploadABCIServices.php';
$up = new UploadABCIServices();
$UpAbci_fragmentSize = $up->returnOctets('2M');
$UpAbci_uniqidForm = $up->getUniqid();
$_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Basique Upload Ajax ABCIWEB</title>
</head>
<body>
<form id="form_base" action="#" method="post">
<input type="file" name="upload_base" multiple="multiple" />
<input type="hidden" value="<?=$UpAbci_fragmentSize?>" name="UpAbci_fragmentSize" />
<input type="hidden" value="<?=$UpAbci_uniqidForm?>" name="UpAbci_uniqidForm" />
<input type="submit" value="Envoyer" />

<div id="reponse_upload">
<div class="UpAbci_infosFile" style="display:none;margin-top:1em;" data-upabcicss-select-file="display:block;">
<span class="UpAbci_imgPreview"></span><!-- vignette de prévisualisation (si le fichier est une image) -->
<span class="UpAbci_name"></span><!-- nom du fichier -->
<progress class="UpAbci_progressionG"></progress> <!-- progression graphique -->
<span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span><!-- pour informer du 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;
while(Bits >= 1000)
{
Bits /= 1000;
Index++;
}
// J'arrondi à 1 chiffre après la virgule pour '', 'K' et 'M', et 3 chiffres après la virgule pour les unités supérieures
Bits = Type[Index] == 'M' || Type[Index] == 'K' || Type[Index] == '' ? Bits.toFixed(1) : Bits.toFixed(3);
var unite = 'b/s';
return(Bits+''+Type[Index]+''+unite);
}

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

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

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

// Cela ne devrait pas arriver mais je vérifie par sécurité que time_upload soit supérieur à 0 pour éventuellement éviter une vilaine division par 0.
if(typeof time_upload === "number" && time_upload > 0)
{
// La propriété "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, validation de formulaire, etc. consultez les autres exemples fournis et les commentaires dans le code source de ces fichiers.