IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Téléchargez Discussion :

Upload de gros fichiers par fragments (chunk)


Sujet :

Téléchargez

  1. #181
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Bonjour,

    Alors voilà mon formulaire simplifié : https://pastebin.com/4Z1UFLEQ

    Et le PHP d'upload UploadAjaxABCI_Upload_Redimensions.php : https://pastebin.com/BQT3ph54 (j'ai retiré certains passages inutiles, no worry !)

    Comme on peut le voir dans mon formulaire, on a la possibilité d'uploader les photos dans un dossier existant ou bien d'en créer un nouveau. Je traite cela au début du fichier UploadAjaxABCI_Upload_Redimensions.php pour avoir la bonne destination pour la suite du script mais du coup pour chaque fichier il va à chaque fois traiter le choix dans le formulaire, ce qui me parait inutile ?
    Surtout que par la suite je compte y placer des logs par la suite pour chaque création (et dans ce cas-là ça me fera autant de logs que de fichiers)

    Avant ce module je bouclais simplement à l'intérieur de mes if (mais en respectant les limites d'OVH)

    EDIT : Je n'arrive pas non plus une fois l'upload fini à récupérer la valeur de la variable $dossier_name_upload (dans le fichier php d'upload) pour l'afficher après sur ma page formulaire. Comment puis-je faire ?

  2. #182
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Salut,
    Citation Envoyé par D333x Voir le message
    Comme on peut le voir dans mon formulaire, on a la possibilité d'uploader les photos dans un dossier existant ou bien d'en créer un nouveau. Je traite cela au début du fichier UploadAjaxABCI_Upload_Redimensions.php pour avoir la bonne destination pour la suite du script mais du coup pour chaque fichier il va à chaque fois traiter le choix dans le formulaire, ce qui me parait inutile.
    C'est relativement inutile, mais dans l'absolu le script php doit être autonome et pouvoir faire les vérifications à chaque appel du script. Et ce n'est pas un isset ou quelques conditions qui vont ralentir l'exécution surtout comparé aux redimensionnements et à l'upload.

    Ne cherche pas à faire des petites optimisations à ce niveau là, surtout si elle pourraient nuire à la sécurité/fiabilité du script, cela dit, tu peux reporter l'essentiel du code qui ne doit être exécuté que lorsque le fichier est complet dans la condition if($fichier_complet != false) pour optimiser un peu.

    Citation Envoyé par D333x Voir le message
    Je n'arrive pas non plus une fois l'upload fini à récupérer la valeur de la variable $dossier_name_upload (dans le fichier php d'upload) pour l'afficher après sur ma page formulaire.
    Oui j'avais vu cela en regardant ton code.

    Attention aussi, tu autorisais également des extensions bmp, avi, mp4 et ico dans ton code php. Si tu veux autoriser l'upload de ces fichiers en complément des images il faudra mettre des conditions dans ton code car la librairie GD de php utilisée pour faire des redimensionnements ne supporte que les fichiers jpg/jpeg, png et gif.

    Voilà donc un exemple de création d'album en reprenant ta méthode qui crée un répertoire pour chaque nouvel album et permet de compléter des albums existants.

    Page du formulaire qui appelle en ajax un fichier nommé "UploadAjaxABCI_Upload_Redimensions_Album.php" :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    <?php
    /* 
    Utilise le fichier "Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php" comme destination Ajax
    */
    session_start();
    header('Content-type: text/html; charset=UTF-8');// Inutile depuis php 5.6
     
    // Charge les classes php avec spl_autoload_register
    spl_autoload_register(function ($class) {require 'Php_Upload/Classes/' . $class . '.php';});
     
    $up = new UploadABCIServices();
     
    $UpAbci_fragmentSize = $up->returnOctets('8M');
     
    // Vérifie si $UpAbci_fragmentSize n'est pas supérieur aux limites du serveur
    $upload_max_filesize = min($up->returnOctets(ini_get('upload_max_filesize')), $up->returnOctets(ini_get('post_max_size')));$UpAbci_fragmentSize = !empty($UpAbci_fragmentSize) && $upload_max_filesize > $UpAbci_fragmentSize ? $UpAbci_fragmentSize : $upload_max_filesize;
     
    $UpAbci_uniqidForm = $up->getUniqid();
     
    // Jeton de formulaire (token);
    $_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>Album photo Upload Ajax ABCIWEB</title>
    <link rel="icon" type="image/png" href="Javascript/Images/favicon.png">
     
    <style type="text/css">
    p {
            padding:0;
            margin:0;
    }
     
    .UpAbci_infosFile {
            word-wrap:break-word;   
    }
     
    .UpAbci_infosFile progress {
            width:100px;
    }
    </style>
    </head>
    <body style="font-family:Arial, Helvetica, sans-serif; font-size:0.9em;max-width:850px;margin:3em auto 0 auto;line-height:1.8em">
     
    <div style="margin-top:3em">
    <form id="form_redim" action="#" method="post">
     <fieldset style="border:3px solid #999;border-radius:5px;padding:1em 1em 1.5em 1em;">
        <legend style="font-size:large">Album Photo </legend>
         <input type="hidden" name="UpAbci_fragmentSize" value="<?=$UpAbci_fragmentSize?>">
         <input type="hidden" name="UpAbci_uniqidForm" value="<?=$UpAbci_uniqidForm?>">
         <input type="file" name="upload" multiple="multiple" style="display:none">
     
     
         <p class="ctrldos">
         <label>Choisir un album existant&nbsp;
         <select name="dossier_name">
             <option value="">Choisissez</option>
             <option value="dossier_1">dossier 1</option>
             <option value="dossier_2">dossier 2</option>
             <option value="dossier_3">dossier 3</option>
         </select></label>
    	 <strong>&nbsp;&nbsp;OU&nbsp;&nbsp;</strong>
         <label>Indiquer un nouvel album&nbsp;<input type="text" name="new_dossier_name" placeholder="Nom du nouvel album"></label>
         </p>
     
         <p style="margin-top:2em">
         <input type="button" class="bouton_custom_file" value="Cliquez ou déposez vos fichiers ici" style="width:300px;height:40px;font-weight:bold;text-align:center;">
     
         <input type="submit" value="Envoyer" style="width:100px;height:40px;font-weight:bold;margin-left:2em">
         </p>
     
         <!-- Bloc conteneur retour d'information générale du serveur -->
         <div class="UpAbci_infosServer" style="display:none" data-upabcicss-submit="display:none" data-upabcicss-select-file="display:none" data-upabcicss-infos-server="display:block"></div>
     
         <!-- Bloc conteneur retour d'information générale contrôle javascript -->
         <p class="erreurs_form" style="display:none;border:2px solid red;color:red;padding:0.5em;margin-top:1em" data-upabcicss-submit="display:none" data-upabcicss-select-file="display:none">Vous n'avez choisi aucune option pour l'album. Merci d'en choisir une.</p>
     
         <!-- Bloc conteneur du retour d'informations spécifiques au fichiers -->
         <div id="reponse_upload" data-upabcicss-select-file="display:block" style="margin-top:2em;">
     
            <!--information du fichier que l'on affiche uniquement si un fichier est sélectionné, pour éviter la barre de progression graphique vide si soumission du formulaire sans fichier-->
             <div class="UpAbci_infosFile" style="display:none;margin-top:1em;clear:both" data-upabcicss-select-file="display:block;">
            	 <hr>
                 <div>
                     <p class="UpAbci_imgPreview" style="float:right"></p><!-- vignettes si le poids total ne dépasse pas la config javascript définie plus bas à 100Mo  -->
     
                    <p>
                    <span class="UpAbci_stop" style="color:red;cursor:pointer;font-size:0.8em;" data-upabcicss-result="cursor:default;opacity:0.5;color:#666">stop </span>
     
                    <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><!-- status (important sinon pas de retour d'information en cas d'erreur) -->
                    </p>
                </div>
     
                <p style="display:none;" data-upabcicss-result-partial="display:block">- sauvegardé : <span class="UpAbci_backup">0 Mo</span></p><!-- S'affichera si une sauvegarde existe en cas d'arrêt ou d'erreur -->
     
             </div>
        </div>
     </fieldset>
    </form>
    </div>
     
    </body>
     
    <script src="Javascript/jquery.js"></script>
    <script src="Javascript/UploadAjaxABCI.js"></script>
     
    <script>
    "use strict"; // Vous pouvez supprimer cette ligne en cas d'utilisation d'autres scripts javascript qui ne supportent pas ce mode.
     
    // Initialisation de la classe javascript (identifiant formulaire, destination ajax, identifiant réponse)
    $(function(){
     
     
    var form_album = $("#form_redim");
    var reponse_upload = $("#reponse_upload");
     
    var dossier_name = form_album.find('.ctrldos').find("select");
    var new_dossier_name = form_album.find('.ctrldos').find("input[type=text]");
     
    // Pour ne pas permettre à la fois une sélection d'album (dossier) et avoir le champ text nouvel album rempli
    dossier_name.on("change",function()
    {
            if(new_dossier_name.val()!='') {
                    $(this).find('option[value=""]').prop('selected', true);
            }
            else if($(this).val()=="") {
                    new_dossier_name.attr("disabled",false);
            }
            else {
                    new_dossier_name.attr("disabled",true);
            }
    })
     
     
    // Destination ajax de l'upload
    var destination_ajax = 'Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php';
     
    var up = new UploadAjaxABCI(destination_ajax, form_album, reponse_upload);
     
    // Met les champs input en readonly durant le téléchargement des fichiers
    up.config.inputFormAttrOnSubmit = "readonly";
     
    // Envoi une requête de fin de traitement de formulaire vers le serveur
    up.config.queryFormEnd = true;
     
    // Interdit la soumission du formulaire sans fichiers joints 
    up.config.submitWithoutFile = false;
     
    // Option pour indiquer un élément html en remplacement du bouton de sélection des fichiers par défaut du navigateur.
    up.config.customFileSelect = ".bouton_custom_file";
     
    // Extensions autorisées
    up.config.filesExtensions = ['jpg','jpeg','png','gif'];
     
    // S'affichera si le redimensionnement et l'upload sont ok.
    up.info.status.ok = "Upload et redimensionnements OK";
     
    // Message d'erreur si problème serveur. Sera complété par le message renvoyé par le serveur pour plus de précision.
    up.info.status.errorServer = "Echec du traitement. ";
     
    up.config.imgPreviewMaxSizeTotal = 200; // en Mo poids total maximum de toutes les photos. Au delà les vignettes ne seront pas affichées.
     
    up.config.imgPreviewMaxWidth = 100; // en pixels, largeur maximale de l'aperçu
    up.config.imgPreviewMaxHeight = 100;// en pixels, hauteur maximale de l'aperçu
     
    // Pour compenser bug sur Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1434496. On utilise FileReader pour la prévisualisation des vignettes, uniquement pour firefox car cette option est gourmande en ressources.
    if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
            up.config.imgPreviewUseFileReader = true;
    }
     
     
    // La fonction config.func_onFormSubmit (si définie) permet d'intercepter et d'interrompre la soumission du formulaire
    up.config.func_onFormSubmit = function(event,tableau){
            
            var message = form_album.find(".erreurs_form");
            
            // Contrôle de la validité du formulaire
            if($.trim(dossier_name.val()) == '' && $.trim(new_dossier_name.val()) == ''){
                    // Fait afficher le message d'erreur avec un effet slide
                    message.slideDown(150);
            }
            else {
                    // Ferme le message avec un effet slide
                    message.slideUp(150);
                    
                    // Pour soumettre l'envoi du formulaire interrompu par la fonction config.func_onFormSubmit
                    up.func_SubmitForm();
            }
    }
     
     
    /* La fonction config.func_FormEnd est exécutée (si définie) à la fin du traitement du formulaire. 
    Je m'en sert ici pour fermer le bloc d'information des fichiers si l'envoi du formulaire a été annulé, en fonction de la valeur de mixte_serveur définie en php avec la méthode addMixteServer. 
    Dans l'exemple de code php, mixte_serveur est utilisé lors du retour des erreurs serveurs pour signaler que le traitement du formulaire a été annulé. On pourrait en faire une toute autre utilisation et notez par ailleurs que mixte_serveur peut accepter tout type de contenu, texte, html ou tableau php qui sera converti automatiquement en objet javascript.
    */
    up.config.func_FormEnd = function(tableau, info_serveur, mixte_serveur){
            if(mixte_serveur == 'annule') {
                    reponse_upload.slideUp(150);
            }
    }
     
    // Démarrage de la fonction, DOM chargé
    up.Start();
    });
    </script>
    </html>

    Page serveur php nommée "UploadAjaxABCI_Upload_Redimensions_Album.php":
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    <?php
    session_start();
     
    header('Content-type: text/html; charset=UTF-8');// Inutile depuis php 5.6
     
    // Charge la classe php d'upload et la classe de redimensionnement avec spl_autoload_register
    spl_autoload_register(function ($class) {require 'Classes/' . $class . '.php';});
     
    // On initialise la classe d'upload sans aucun paramètre. La destination du fichier sera définie par le paramètre passé dans la fonction Tranfert()
    $up = new UploadAjaxABCIServeur();
     
    // Décommenter la ligne ci-dessous en phase de développement pour faire afficher les erreurs php dans le formulaire.
    // $up->setModeDebug ();
     
     
    // Voir le mode d'emploi pour des informations complémentaires sur la gestion des erreurs fatales.
    $tab_erreurs = [];
    $tab_erreurs['Allowed memory size'] = SetMessages::get('UpAbAllowedMemorySize');
    $tab_erreurs['Maximum execution time'] = SetMessages::get('UpAbMaximumExecutionTime');
    $up->cathErrorServeur($tab_erreurs);
     
    $uniqid_form = $up->getParam("uniqid_form");
     
    if(!(isset($uniqid_form,$_SESSION['UploadAjaxABCI'][$uniqid_form]['token']))) $up->exitStatusErreur(SetMessages::get('UpAbVerifToken')); 
     
    /* 
    On crée une variable de session pour enregistrer différents résultats qu'on utilisera en fin de traitement du formulaire dans la condition "if(count($up->UpAbci_formEnd) > 0)"
    
    J'utilise des variables de session sous la forme $_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['index'] pour préserver l'espace de nom. Et j'assigne ces variables par référence à d'autres variables pour simplifier l'écriture. Attention de ne pas utiliser l'index "token" qui est déjà utilisé.
    */
    function &sesInit($uniqid_form, $index, $defaut)
    {
    	$_SESSION['UploadAjaxABCI'][$uniqid_form][$index] = isset($_SESSION['UploadAjaxABCI'][$uniqid_form][$index]) ?  $_SESSION['UploadAjaxABCI'][$uniqid_form][$index] : $defaut;
     
    	return $_SESSION['UploadAjaxABCI'][$uniqid_form][$index];
    }
     
    // Initialisation d'une variable de session pour enregistrer le dossier de destination.
    $ses_dossier =& sesInit($uniqid_form, 'dossier', null);
     
    // Initialisation d'une variable de session pour enregistrer la création d'un nouveau dossier.
    $ses_new_dossier =& sesInit($uniqid_form, 'new_dossier', null);
     
    // Initialisation d'une variable de session pour enregistrer les fichiers.  
    $ses_fichiers =& sesInit($uniqid_form, 'fichiers', []);
     
     
    /*
    Création d'une fonction qui stoppe le traitement de l'ensemble du formulaire a réception de la requête ajax, 
    Ajoute un message dans le bloc html ayant la classe UpAbci_infosServer avec addInfosServer 
    et/ou 
    passe un objet dans mixte_serveur avec addMixteServer - récupérable dans la fonction événementielle config.func_FormEnd - , 
    et sort du script php en cours.
    */
    function stopFormExit ($up, $infos_server=null, $mixte_server=null)
    {
    	// Commande à javascript de stopper la soumission du formulaire à réception de la requête ajax.
    	$up->stopForm();
    	// addInfosServer envoie un message dans le bloc html ayant la classe UpAbci_infosServer
    	if(isset($infos_server)) $up->addInfosServer ($infos_server);
    	// addMixteServer passe un objet (texte, html ou tableau) qui pourra être récupéré en troisisème paramètre dans la fonction événementielle "config.func_FormEnd"
    	if(isset($mixte_server)) $up->addMixteServer ($mixte_server);
    	// Et sort du traitement php en envoyant les informations nécessaires vers javascript
    	$up->exitReponseAjax();
    }
     
     
    // Création d'une fonction pour avoir des noms de dossier valides sur tous les serveurs
    function cleanDossier($up, $name)
    {
    	// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    	$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Nom d\'album "<strong>'.htmlspecialchars($name).'</strong>" non valide. Traitement du formulaire annulé.</div>';
    	/*
    	On supprime les séparateurs de dossiers et les points pour rendre la chaine compatible avec l'utilisation de la méthode cleanFileName qui est normalement prévue pour nettoyer des fichiers.
    	*/
    	$name_dos = str_replace (['/','.'], ['',''], $name);
    	// Il ne faut pas passer une chaine vide à la fonction de nettoyage
    	if($name_dos == '') {stopFormExit ($up, $message, 'annule');}
    	// On nettoie la chaine avec la méthode cleanFileName() de la classe d'upload
    	$name_dos = $up->cleanFileName($name_dos);
    	// On re vérifie après nettoyage
    	if($name_dos == '') {stopFormExit ($up, $message, 'annule');}
     
    	return $name_dos;
    }
     
    /* 
    Ne pas mettre ces lignes à l'intérieur de la condition "if $up->getFragment" car ces variables sont utilisées en fin de page pour exploiter la requête additionnelle de fin de traitement du formulaire qui ne contient pas de fragment de fichier.
    */
    $dossier_name_post = isset($_POST['dossier_name']) && trim($_POST['dossier_name']) != '' ? cleanDossier($up, trim($_POST['dossier_name'])) : null;
    $new_dossier_name_post = isset($_POST['new_dossier_name']) && trim($_POST['new_dossier_name']) != '' ? cleanDossier($up, trim($_POST['new_dossier_name'])) : null;
     
     
    // S'assure qu'un fichier ou un fragment de fichier est en téléchargement
    if($up->getFragment())
    {
    	$filesExtensions = ['jpg','jpeg','png','gif'];
     
    	$nom_fichier_nettoye = $up->getCleanFileName();
     
    	$verif_extension = $up->verifExtensions($nom_fichier_nettoye,$filesExtensions);
    	if($verif_extension == false) 
    	{
    		$up->exitStatusErreur(SetMessages::get('UpAbExtensionFichier'));
    	}	
     
    	// Par sécurité on refait le contrôle déjà effectué en javascript
    	if($dossier_name_post == '' && $new_dossier_name_post == '')
    	{
    		$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Vous n\'avez choisi aucune option pour l\'album. Merci d\'en choisir une. Traitement du formulaire annulé.</div>';
    		stopFormExit ($up, $message, 'annule');
    	}
     
     
    	// Upload dans le dossier temporaire
    	$up->Upload();
     
    	// Retourne l'adresse du fichier temporaire quand il est complet, sinon false
    	$fichier_complet = $up->getTempAdressFileComplete();
    	if($fichier_complet != false)
    	{
    		$repertoire = '../../../photos/';		
     
    		if($new_dossier_name_post != '') 
    		{
    			if(!is_dir($repertoire.$new_dossier_name_post.'/mini'))
    			{
    				if(mkdir($repertoire.$new_dossier_name_post.'/mini', 0777, true))
    				{
    					$fp = fopen($repertoire.$new_dossier_name_post.'/index.php', 'w');
    					$contenuindexphp = '[...]';
     
    					fwrite($fp, $contenuindexphp);
    					fclose($fp);
     
    					$ses_new_dossier = $new_dossier_name_post;
    				}
    				else
    				{
    					// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    					$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Erreur dans la création du dossier "'.htmlspecialchars($new_dossier_name_post).'". Traitement du formulaire annulé.</div>';
    					stopFormExit ($up, $message, 'annule');
    				}
    			}
     
    			$dossier_name_upload = $new_dossier_name_post;
    		}
    		else if(is_dir($repertoire.$dossier_name_post.'/mini'))
    		{
    			$dossier_name_upload = $dossier_name_post;
    		}
    		else
    		{
    			// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    			$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Le dossier sélectionné "'.htmlspecialchars($dossier_name_post).'" n\'est pas valide. Traitement du formulaire annulé.</div>';
    			stopFormExit ($up, $message, 'annule');
    		}
     
    		$dossier_destination = $repertoire.$dossier_name_upload .'/';
    		$dossier_mini = $repertoire.$dossier_name_upload .'/mini/';
     
    		$ses_dossier = $dossier_name_upload;
     
    		/* 
    		La classe CorrectionExifJpg corrige l'orientation des images jpg en fonction de ses informations EXIF. 
    		Il faut l'utiliser avant les traitements sur les images car les largeurs et hauteurs pourront être inversées. 
    		Cette classe peut émettre des exceptions, à utiliser dans un bloc try/catch. 
    		*/
    		try 
    		{ 	
    			CorrectionExifJpg::filePath($fichier_complet);
    		}
    		catch (Exception $e) 
    		{
    			$up->exitStatusErreur($e->getMessage());
    		}
     
     
    		/*
    		Si plusieurs redimensionnements on utilise les troisième et quatrième paramètre de la classe "RedimImage()" qui vont copier le fichier redimensionné dans le répertoire de destination et laisser intact le fichier original.
    		Ci-dessous je crée une fonction qui réalise la redimension et impose le chmod au fichier de destination
    		
    		La fonction RedimImage peut renvoyer des exceptions, il faut donc utiliser un bloc try/catch
    		*/
    		function Redim($L, $H, $dossier_dest=null, $nom_fichier=null, $dirname, $basename, $extension_fichier, $up)
    		{
    			try
    			{
    				RedimImage::Param($L, $H, $dossier_dest, $nom_fichier, $dirname, $basename, $extension_fichier);
    			}
    			catch (Exception $e)
    			{
    				$up->exitStatusErreur($e->getMessage());
    			}
     
    			// On met le chmod si besoin (mini 0604 pour une lecture depuis une url externe) au cas où le serveur mette un 0600
    			$destination_fichier = $dossier_dest.$nom_fichier;
    			if(trim($destination_fichier) != '' && !@chmod($destination_fichier,0604))
    			{
    				$up->exitStatusErreur(SetMessages::get('UpAbConfigChmod'));
    			}
    		}
     
    		// Informations sur le fichier
    		$pathinfo = pathinfo($nom_fichier_nettoye);
    		$extension_fichier = strtolower($pathinfo['extension']);
    		$non_fichier = $pathinfo['filename'];
     
    		// On utilise l'adresse du fichier temporaire (fichier de travail) pour le passer en paramètre à la fonction de redimensionnement
    		$basename = basename($fichier_complet);
    		$dirname = dirname($fichier_complet).'/';
     
    		/* 
    		On fait le plus grand redimensionnement en premier dans le répertoire temporaire en modifiant la source. Les redimensionnements suivants utiliseront cette image redimensionnée et donc moins de ressources serveur par rapport à l'image originale. Il faut bien entendu que les redimensionnements suivants soient de dimensions inférieures.
    		*/
    		Redim(1500, 1500, '', '', $dirname, $basename, $extension_fichier, $up);
    		// On construit l'adresse du premier fichier redimensionné pour le passer en paramètre à la fonction "Transfert()"
    		$nom_fichier_max = $non_fichier.'.'.$extension_fichier;
    		$destination_fichier = $dossier_destination.$nom_fichier_max;
     
    		// Redimensionnements suivants en utilisant le premier comme source et en copiant le résultat dans le répertoire de destination (ne modifie pas la source)
    		$nom_fichier_min = $non_fichier.'.'.$extension_fichier;
    		Redim(150, 150, $dossier_mini, $nom_fichier_min, $dirname, $basename, $extension_fichier, $up);
     
    		// La fonction "Transfert()" transfère le fichier du répertoire temporaire vers sa destination finale. Retourne true si ok. 
    		$transfert = $up->Transfert($destination_fichier);
     
    		// On défini le chmod (si besoin)
    		if($transfert && !@chmod($destination_fichier,0604))
    		{
    			$up->exitStatusErreur(SetMessages::get('UpAbConfigChmod'));
    		}
     
    		// Si on arrive ici c'est que tout c'est bien passé, sinon les $up->exitStatusErreur() utilisés en cas d'erreur arrêtent le script et envoient le message correspondant. On pourrait donc enregistrer ici le(s) nom(s) du fichier en bdd. 
     
    		if($transfert)
    		{			
    			/* 
    			J'enregistre les données dans des variables de session qui seront exploitées à la fin du traitement du formulaire. Mais si une panne internet ou une coupure de courant survient avant la fin du traitement de tout le formulaire, on ne pourra pas utiliser ces données car le tableau UpAbci_formEnd exploité plus loin pour récupérer ces données ne sera jamais reçu. Même si les pannes sont rares, il faut donc éviter d'utiliser cette méthode pour des traitements dont l'absence pourrait perturber l'intégrité des données du site.
    			
    			Il serait plus sécurisé de loguer les fichiers uploadés ici (dans la condition if($transfert)) les uns après les autres pour être certain de n'en manquer aucun.
    			
    			$up->getParam("name") retourne le nom originel du fichier. J'utilise cette construction pour pouvoir récupérer facilement le nom du fichier nettoyé avec le tableau récapitulatif UpAbci_formEnd retourné en fin de traitment du formulaire.
    			*/
    			$ses_fichiers[$up->getParam("name")] = $nom_fichier_nettoye;
    		}		
    	}
    }
     
     
     
    /* 
    Si ET SEULEMENT SI on défini l'option "config.queryFormEnd = true" dans la configuration javascript du formulaire, une requête additionnelle est envoyée vers le serveur à la fin du traitement du formulaire. Elle contient les variables $_POST communes à tout le formulaire (non spécifiques à chaque fichier), et un tableau récapitulatif de l'upload pour chaque fichier récupérable avec la propriété "UpAbci_formEnd" de la classe php. 
    
    Si ce n'est pas la fin du traitement du formulaire ou si l'option javascript n'est pas configurée, $up->UpAbci_formEnd renvoie un tableau vide. Cf mode d'emploi "Configuration serveur -> Récupération des paramètres Ajax prédéfinis".
    */
    if(count($up->UpAbci_formEnd) > 0)
    {
    	// Ici on peut exploiter $ses_fichiers, $ses_dossier et $ses_new_dossier en pensant à les effacer à la fin du traitement pour éviter un cumul en cas d'envois sucessifs du formulaire.
     
    	// On peut vérifier que les fichiers ont été correctement transférés en testant l'index "result" qui doit retourner "ok_done".
    	$result = 0;
    	foreach($up->UpAbci_formEnd as $file)
    	{
    		if($file['result'] == "ok_done")
    		{
    			$result++;
     
    			/* 
    			pour info :
    			- le nom originel du fichier est $file['name']
    			- le nom du fichier nettoyé est donc $ses_fichiers[$file['name']] 
    			Attention : si vous souhaitez récupérer $ses_fichiers[$file['name']] en dehors de la condition if($file['result'] == "ok_done"), il faudra le tester avec "isset" car cet item n'est défini que pour les fichiers transférés (cf la construction de la variable de session $ses_fichiers plus haut à l'intérieur de la condition if ($transfert)).
    			*/
    		}
    	}
     
    	$message_debut = $result == count($up->UpAbci_formEnd) ? 'Toutes les photos ont bien été ajoutées dans l\'album. <br />' : 'Certaines photos n\'ont pas été ajoutées dans l\'album. Voir le détail dans la liste ci-dessous.<br />';
     
    	// Je construis un message différent si un nouveau répertoire a été créé ou non.
    	// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    	$message = $ses_new_dossier == $new_dossier_name_post ? 
    	$message_debut.'Adresse du nouvel album : <a target="_blank" href="../../photos/'.htmlspecialchars($ses_dossier).'/">https://'.$_SERVER['HTTP_HOST'].'/photos/'.htmlspecialchars($ses_dossier).'/</a> <br /><span style="color: red; font-weight: bold;">/!\ Il est important de rajouter l\'adresse de l\'album dans la page "Album" du site. <a href="../contenus/edit?id=18">Cliquez ici pour le faire après avoir copié l\'adresse de l\'album ci-dessus </a> /!\</span>'
    	:
    	$message_debut;
     
    	$message = '<div style="border:2px solid #F90;color:black;padding:0.5em;margin-top:1em">'.$message.'</div>';
     
     
    	// Pour envoyer le message dans l'élément html ayant la classe UpAbci_infosServer
    	$up->addInfosServer($message);
     
     
    	// Ne pas oublier de supprimer les variables de session en fin de traitement du formulaire (unset() ne fonctionne pas pour les variables passées par référence).
    	$ses_fichiers = null;
    	$ses_dossier = null;
    	$ses_new_dossier = null;
     
     
    	// Pour voir facilement le contenu de UpAbci_formEnd en phase de développement (sera affiché dans l'élément html ayant la classe UpAbci_infosServer)
    	/*
    	ob_start();
    	echo '<pre>'.var_dump($up->UpAbci_formEnd).'</pre>';
    	$dump = ob_get_contents();
    	ob_end_clean();
    	$up->addInfosServer($dump);
    	*/
     
    }
     
    $up->exitReponseAjax();
    ?>
    Pour tester, copie la page du formulaire dans le même répertoire que les formulaires dans le module d'upload, et le code php dans le répertoire "Php_Upload".

    Le code est commenté et devrait répondre à tes questions.

    J'ai fait des contrôles javascript et des contrôles de sécurité côté serveur avec des messages qui seront retournés en cas de besoin.

    Ensuite tu pourrais fignoler encore en réservant la hauteur des images de prévisualisation (sinon le formulaire fait l'accordéon le temps d'afficher toutes les images), prends exemple sur le fichier "UploadAjaxABCI_Custom.php" si besoin.

    Testes les fonctionnalités et dis-moi si c'est OK

  3. #183
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Bonjour,

    Un tout tout tout grand merci ! C'est exactement ce qu'il me fallait et grâce aux commentaires dans le code j'ai pu le modifier pour l'adapter un tout petit peu !
    Super !

    Merci beaucoup !
    Bon weekend

  4. #184
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Bonsoir,

    Après avoir mis en ligne le code, j'ai déjà remarqué une toute petite coquille ...

    J'ai mis dans le code l'insertion en BDD de logs de sécurité (2 logs différents en fonction de si on crée un album ou si on utilise un album existant).

    J'ai placé les logs entre la ligne 136 et 137 (pour la création d'un album) et entre la ligne 150 et 151 (pour l'utilisation d'un album existant).
    Dans le premier cas, le log s'enregistre bien une seule fois mais je viens de remarquer que lorsque l'on insert des photos dans un album existant (2ème cas, ligne 150-151), il y a autant de log que de photos qui s'enregistrent en BDD.

    Ma question est donc la suivante : Où devrais-je faire d'une façon optimale l'insertion en BDD de mes logs de sécurité ?

    Encore un grand merci !

  5. #185
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Salut,

    Je te donne un exemple avec toutes les possibilités :
    - Log à la fin du traitement du formulaire.
    - Log à chaque rafraichissement de la page du formulaire.
    - Log une seule fois par session utilisateur.

    J'ai aussi complété la fonction stopFormExit qui ne supprimait pas les variables de sessions. C'était un oubli sans conséquence dans la configuration actuelle, mais sur le principe autant le faire pour éviter des effets de bords non prévus.

    Une fonction unsetSesInit a été créée pour faciliter la supression des variables de sessions et la fonction sesInit a été modifiée en conséquence.

    D'autres améliorations ont été mises en place pour traiter le cas où un utilisateur saisirait un nom de dossier existant dans le champ "nouvel album", et pour l'affichage de la création d'un nouvel album.

    Bref il y a eu des changements et les explications détaillées sont dans le code source. J'ai traité a peu près tous les cas de figure possibles côté serveur.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    <?php
    session_start();
     
    header('Content-type: text/html; charset=UTF-8');// Inutile depuis php 5.6
     
    // Charge la classe php d'upload et la classe de redimensionnement avec spl_autoload_register
    spl_autoload_register(function ($class) {require 'Classes/' . $class . '.php';});
     
    // On initialise la classe d'upload sans aucun paramètre. La destination du fichier sera définie par le paramètre passé dans la fonction Tranfert()
    $up = new UploadAjaxABCIServeur();
     
    // Décommenter la ligne ci-dessous en phase de développement pour faire afficher les erreurs php dans le formulaire.
    // $up->setModeDebug ();
     
     
    // Voir le mode d'emploi pour des informations complémentaires sur la gestion des erreurs fatales.
    $tab_erreurs = [];
    $tab_erreurs['Allowed memory size'] = SetMessages::get('UpAbAllowedMemorySize');
    $tab_erreurs['Maximum execution time'] = SetMessages::get('UpAbMaximumExecutionTime');
    $up->cathErrorServeur($tab_erreurs);
     
    $uniqid_form = $up->getParam("uniqid_form");
     
    if(!(isset($uniqid_form,$_SESSION['UploadAjaxABCI'][$uniqid_form]['token']))) $up->exitStatusErreur(SetMessages::get('UpAbVerifToken')); 
     
    /* 
    J'utilise des variables de session sous la forme $_SESSION['UploadAjaxABCI'][$index1][$index2] pour préserver l'espace de nom. Et j'assigne ces variables par référence à d'autres variables pour simplifier l'écriture. Attention de ne pas utiliser l'index2 "token" qui est déjà utilisé.
    */
    function &sesInit($index1, $index2, $defaut, $unset = true)
    {
    	$_SESSION['UploadAjaxABCI'][$index1][$index2] = isset($_SESSION['UploadAjaxABCI'][$index1][$index2]) ? 	$_SESSION['UploadAjaxABCI'][$index1][$index2] : $defaut;
     
    	// Enregistre les index des variables de session à effacer en fin de traitement du formulaire
    	if($unset) {$_SESSION['UploadAjaxABCI'][$index1]['unsetSesInit'][] = $index2;}
     
    	return $_SESSION['UploadAjaxABCI'][$index1][$index2];
    }
     
    // Initialisation d'une variable de session pour enregistrer les fichiers.  
    $ses_fichiers =& sesInit($uniqid_form, 'fichiers', []);
     
    // Initialisation d'une variable de session pour enregistrer le dossier de destination.
    $ses_dossier =& sesInit($uniqid_form, 'dossier', null);
     
    // Initialisation d'une variable de session pour enregistrer la création d'un nouveau dossier. "false" est passé en 4ème paramètre pour éviter la suppression de cette variable de session en fin de traitement du formulaire. Cela permettra au visiteur de compléter un nouvel album nouvellement créé tant qu'il n'a pas rafraichi la page du formulaire, voir la construction de if(!isset($ses_new_dossier)) plus loin dans le code.
    $ses_new_dossier =& sesInit($uniqid_form, 'new_dossier', null, false);
     
    // Initialisation d'une variable de session pour enregistrer l'affichage du message de création de nouvel album.
    $ses_new_dossier_message =& sesInit($uniqid_form, 'new_dossier_message', null);
     
    // Initialisation d'une variable de session pour mettre à jour le select dans le html.
    $ses_new_select =& sesInit($uniqid_form, 'new_select', null);
     
     
     
    /* 
    Initialisation d'une variable de session pour enregistrer le log d'un dossier existant qui a été complété. Trois cas sont possibles :
    
    1/ Log à chaque rafraichissement de la PAGE du formulaire
    - "false" est passé en 4ème paramètre pour éviter la suppression de cette variable de session en fin de traitement du formulaire.
    
    2/ Log à chaque envoi du formulaire
    - Si vous souhaitez faire le log du dossier systématiquement à chaque envoi du formulaire même si le dossier est identique à l'envoi précédent (dans le cas d'envois successifs du formulaire sans rafraichissement de la page), supprimez le paramètre false.
    
    Notez que dans ces deux cas (avec ou sans le paramètre false), cette variable de session est réinitialisée automatiquement à chaque rafraichissement de la PAGE du formulaire puisqu'elle est construite avec la variable dynamique $UpAbci_uniqidForm (= $uniqid_form) envoyée par le formulaire :
    */
    // $ses_log_dossier_selection =& sesInit($uniqid_form, 'log_dossier_selection', null, false);
     
     
    /*
    3/ Log une seule fois par session utilisateur
    - Pour faire un log une seule fois par session tant que le dossier sélectionné n'a pas changé, utilisez une variable de session avec des index statiques, par exemple en utilisant $up->getParam("id_form") qui retourne l'identifiant (id ou class) du formulaire :
    */
    $ses_log_dossier_selection =& sesInit($up->getParam("id_form"), 'log_dossier_selection', null, false);
     
     
     
    // Fonction pour supprimer les variables de session enregistrées dans $_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit'] 
    function unsetSesInit($uniqid_form)
    {
    	// N'efface que les variables dynamiques construites avec $uniqid_form
    	if(isset($_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit']))
    	{
    		foreach($_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit'] as $index2)
    		{
    			unset($_SESSION['UploadAjaxABCI'][$uniqid_form][$index2]);
    		}
    		unset($_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit']);
    	}
    }
     
    /*
    Création d'une fonction qui :
    - Stoppe le traitement de l'ensemble du formulaire a réception de la requête ajax, 
    - Ajoute un message dans le bloc html ayant la classe UpAbci_infosServer avec addInfosServer 
    et/ou 
    - Passe un objet dans mixte_serveur avec addMixteServer, récupérable dans la fonction événementielle config.func_FormEnd 
    - Efface les variables de session enregistrées dans 'unsetSesInit'
    - Et sort du script php en cours.
    */
    function stopFormExit ($up, $infos_server=null, $mixte_server=null)
    {
    	// Commande à javascript de stopper la soumission du formulaire à réception de la requête ajax.
    	$up->stopForm();
    	// addInfosServer envoie un message dans le bloc html ayant la classe UpAbci_infosServer
    	if(isset($infos_server)) $up->addInfosServer ($infos_server);
    	// addMixteServer passe un objet (texte, html ou tableau) qui pourra être récupéré en troisisème paramètre dans la fonction événementielle "config.func_FormEnd"
    	if(isset($mixte_server)) $up->addMixteServer ($mixte_server);
    	// Efface certaines variables de sessions (cf unsetSesInit)
    	unsetSesInit($up->getParam("uniqid_form"));
    	// Et sort du traitement php en envoyant les informations nécessaires vers javascript
    	$up->exitReponseAjax();
    }
     
     
    // Création d'une fonction pour avoir des noms de dossier valides sur tous les serveurs
    function cleanDossier($up, $name)
    {
    	// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    	$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Nom d\'album "<strong>'.htmlspecialchars($name).'</strong>" non valide. Traitement du formulaire annulé.</div>';
    	/*
    	On supprime les séparateurs de dossiers et les points pour rendre la chaine compatible avec l'utilisation de la méthode cleanFileName qui est normalement prévue pour nettoyer des fichiers.
    	*/
    	$name_dos = str_replace (['/','.'], ['',''], $name);
    	// Il ne faut pas passer une chaine vide à la fonction de nettoyage
    	if($name_dos == '') {stopFormExit ($up, $message, 'annule');}
    	// On nettoie la chaine avec la méthode cleanFileName() de la classe d'upload
    	$name_dos = $up->cleanFileName($name_dos);
    	// On re vérifie après nettoyage
    	if($name_dos == '') {stopFormExit ($up, $message, 'annule');}
     
    	return $name_dos;
    }
     
    /* 
    Ne pas mettre ces lignes à l'intérieur de la condition "if $up->getFragment" car ces variables sont utilisées en fin de page pour exploiter la requête additionnelle de fin de traitement du formulaire qui ne contient pas de fragment de fichier.
    */
    $dossier_name_post = isset($_POST['dossier_name']) && trim($_POST['dossier_name']) != '' ? cleanDossier($up, trim($_POST['dossier_name'])) : null;
    $new_dossier_name_post = isset($_POST['new_dossier_name']) && trim($_POST['new_dossier_name']) != '' ? cleanDossier($up, trim($_POST['new_dossier_name'])) : null;
     
     
    // S'assure qu'un fichier ou un fragment de fichier est en téléchargement
    if($up->getFragment())
    {
    	$filesExtensions = ['jpg','jpeg','png','gif'];
     
    	$nom_fichier_nettoye = $up->getCleanFileName();
     
    	$verif_extension = $up->verifExtensions($nom_fichier_nettoye,$filesExtensions);
    	if($verif_extension == false) 
    	{
    		$up->exitStatusErreur(SetMessages::get('UpAbExtensionFichier'));
    	}	
     
    	// Par sécurité on refait le contrôle déjà effectué en javascript
    	if($dossier_name_post == '' && $new_dossier_name_post == '')
    	{
    		$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Vous n\'avez choisi aucune option pour l\'album. Merci d\'en choisir une. Traitement du formulaire annulé.</div>';
    		stopFormExit ($up, $message, 'annule');
    	}
     
     
    	// Upload dans le dossier temporaire
    	$up->Upload();
     
    	// Retourne l'adresse du fichier temporaire quand il est complet, sinon false
    	$fichier_complet = $up->getTempAdressFileComplete();
    	if($fichier_complet != false)
    	{
    		$repertoire = '../../../photos/';
     
    		$log_dossier_selection = null;
     
    		if($new_dossier_name_post != '') 
    		{
    			if(!is_dir($repertoire.$new_dossier_name_post.'/mini'))
    			{
    				if(mkdir($repertoire.$new_dossier_name_post.'/mini', 0777, true))
    				{
    					$ses_new_dossier = $new_dossier_name_post;
     
    					// Variable utilisée pour ne faire afficher le message de création d'album qu'une fois (tant que le visiteur n'a pas rafraichit sa page).
    					$ses_new_dossier_message = $new_dossier_name_post;
     
    					// Log un nouveau dossier a été créé
    					// ...
     
    					$fp = fopen($repertoire.$new_dossier_name_post.'/index.php', 'w');
    					$contenuindexphp = '[...]';
     
    					fwrite($fp, $contenuindexphp);
    					fclose($fp);
     
    					// On enregsitre le tableau du nouveau dossier qui sera passé vers javascript avec addmixteServer et récupérable dans la fonction événementielle up.config.func_FormEnd 
    					$ses_new_select = [$new_dossier_name_post => str_replace('-',' ',$new_dossier_name_post)];
    				}
    				else
    				{
    					// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    					$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Erreur dans la création du dossier "'.htmlspecialchars(str_replace('-',' ',$new_dossier_name_post)).'". Traitement du formulaire annulé.</div>';
    					stopFormExit ($up, $message, 'annule');
    				}
    			}
    			else if(!isset($ses_new_dossier) || $ses_new_dossier != $new_dossier_name_post)
    			{
    				/* On arrive dans cette condition si 
    				1/ le visiteur a utilisé le champ "nouvel album" et a saisi le nom d'un dossier déjà existant (aucun dossier n'a été créé) 
    				ou
    				2/ Après avoir créé un nouvel album, il tente d'un créer un second en rentrant le nom d'un dossier déjà existant et donc dans ce cas $ses_new_dossier != $new_dossier_name_post. (se souvenir que $ses_new_dossier n'est réinitialisée qu'au chargement de la page ou intialisée uniquement si un nouveau dossier a été créé)
    				*/
     
     
    				/*
    				Plutôt que d'autoriser l'upload on peut annuler le formulaire et envoyer un message d'erreur car l'action ne correspond pas à la création d'un nouvel album (c'est sans doute une erreur involontaire du visiteur).
    				
    				Notez que la variable de session $ses_new_dossier ne sera réinitialisée que lors du rafraichissement de la page du formulaire, cf sa définition avec le quatrième paramètre lors de sa défintition avec sesInit (en début de script). Cela permettra au visiteur de compléter un album nouvellement créé tant qu'il n'a pas rafraichi la page du formulaire.
    				*/
    				$message = !isset($ses_new_dossier) ? 
    				'<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Le nouvel album "'.htmlspecialchars(str_replace('-',' ',$new_dossier_name_post)).'" existe déjà. Utilisez le sélecteur d\'album pour compléter un album existant.<br> Traitement du formulaire annulé.</div>'
    				:
    				'<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Le nouvel album "'.htmlspecialchars(str_replace('-',' ',$new_dossier_name_post)).'" a déjà été créé. Utilisez le sélecteur d\'album pour compléter un album existant.<br> Traitement du formulaire annulé.</div>';
     
     
    				stopFormExit ($up, $message, 'annule');
     
    				/*
    				Alternativement on pourrait autoriser l'upload sans avertissement mais dans ce cas il faudrait loguer le dossier qui sera complété.
    				On pourrait faire le log ici mais si l'on souhaite enregistrer un dossier réellement complété mieux vaut le faire dans la condition if($transfert), car ici le fichier n'est ni transféré ni traité et il pourrait être rejeté si une erreur survient lors des redimensionnements d'images par exemple (ainsi le dossier ne serait pas complété). On enregistrera donc une variable témoin pour faire le log plus loin dans la condition if(transfert).
    				*/
    				/*
    				if ($new_dossier_name_post != $ses_log_dossier_selection)
    				{
    					// On enregistre le dossier dans la variable de session
    					$ses_log_dossier_selection = $new_dossier_name_post;
    										
    					// On enregistre une variable témoin pour faire le log dans la condition if (transfert)
    					$log_dossier_selection = $new_dossier_name_post;
    				}
    				*/
    			}
     
    			$dossier_name_upload = $new_dossier_name_post;
     
    		}
    		else if ($dossier_name_post != '') // Sélection d'album
    		{
    			if(is_dir($repertoire.$dossier_name_post.'/mini'))
    			{
    				$dossier_name_upload = $dossier_name_post;
     
    				// Si le dossier est différent de celui déjà enregistré
    				if ($dossier_name_post != $ses_log_dossier_selection)
    				{
    					// On enregistre le dossier dans la variable de session
    					$ses_log_dossier_selection = $dossier_name_post;
     
    					// On pourrait faire le log ici mais même remarque que dans la deuxième partie de la condition if(!isset($ses_new_dossier)) quelques lignes plus haut : on enregistre une variable témoin pour faire le log plus loin dans la condition if (transfert)
    					$log_dossier_selection = $dossier_name_post;
    				}
    			}
    			else
    			{
    				// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    				$message = '<div style="border:2px solid red;color:red;padding:0.5em;margin-top:1em">Le dossier sélectionné "'.htmlspecialchars(str_replace('-',' ',$dossier_name_post)).'" n\'est pas valide. Traitement du formulaire annulé.</div>';
    				stopFormExit ($up, $message, 'annule');
    			}
    		}
     
    		$dossier_destination = $repertoire.$dossier_name_upload .'/';
    		$dossier_mini = $repertoire.$dossier_name_upload .'/mini/';
     
    		$ses_dossier = $dossier_name_upload;
     
    		/* 
    		La classe CorrectionExifJpg corrige l'orientation des images jpg en fonction de ses informations EXIF. 
    		Il faut l'utiliser avant les traitements sur les images car les largeurs et hauteurs pourront être inversées. 
    		Cette classe peut émettre des exceptions, à utiliser dans un bloc try/catch. 
    		*/
    		try 
    		{ 	
    			CorrectionExifJpg::filePath($fichier_complet);
    		}
    		catch (Exception $e) 
    		{
    			$up->exitStatusErreur($e->getMessage());
    		}
     
     
    		/*
    		Si plusieurs redimensionnements on utilise les troisième et quatrième paramètre de la classe "RedimImage()" qui vont copier le fichier redimensionné dans le répertoire de destination et laisser intact le fichier original.
    		Ci-dessous je crée une fonction qui réalise la redimension et impose le chmod au fichier de destination
    		
    		La fonction RedimImage peut renvoyer des exceptions, il faut donc utiliser un bloc try/catch
    		*/
    		function Redim($L, $H, $dossier_dest=null, $nom_fichier=null, $dirname, $basename, $extension_fichier, $up)
    		{
    			try
    			{
    				RedimImage::Param($L, $H, $dossier_dest, $nom_fichier, $dirname, $basename, $extension_fichier);
    			}
    			catch (Exception $e)
    			{
    				$up->exitStatusErreur($e->getMessage());
    			}
     
    			// On met le chmod si besoin (mini 0604 pour une lecture depuis une url externe) au cas où le serveur mette un 0600
    			$destination_fichier = $dossier_dest.$nom_fichier;
    			if(trim($destination_fichier) != '' && !@chmod($destination_fichier,0604))
    			{
    				$up->exitStatusErreur(SetMessages::get('UpAbConfigChmod'));
    			}
    		}
     
    		// Informations sur le fichier
    		$pathinfo = pathinfo($nom_fichier_nettoye);
    		$extension_fichier = strtolower($pathinfo['extension']);
    		$non_fichier = $pathinfo['filename'];
     
    		// On utilise l'adresse du fichier temporaire (fichier de travail) pour le passer en paramètre à la fonction de redimensionnement
    		$basename = basename($fichier_complet);
    		$dirname = dirname($fichier_complet).'/';
     
    		/* 
    		On fait le plus grand redimensionnement en premier dans le répertoire temporaire en modifiant la source. Les redimensionnements suivants utiliseront cette image redimensionnée et donc moins de ressources serveur par rapport à l'image originale. Il faut bien entendu que les redimensionnements suivants soient de dimensions inférieures.
    		*/
    		Redim(1500, 1500, '', '', $dirname, $basename, $extension_fichier, $up);
    		// On construit l'adresse du premier fichier redimensionné pour le passer en paramètre à la fonction "Transfert()"
    		$nom_fichier_max = $non_fichier.'.'.$extension_fichier;
    		$destination_fichier = $dossier_destination.$nom_fichier_max;
     
    		// Redimensionnements suivants en utilisant le premier comme source et en copiant le résultat dans le répertoire de destination (ne modifie pas la source)
    		$nom_fichier_min = $non_fichier.'.'.$extension_fichier;
    		Redim(150, 150, $dossier_mini, $nom_fichier_min, $dirname, $basename, $extension_fichier, $up);
     
    		// La fonction "Transfert()" transfère le fichier du répertoire temporaire vers sa destination finale. Retourne true si ok. 
    		$transfert = $up->Transfert($destination_fichier);
     
    		// On défini le chmod (si besoin)
    		if($transfert && !@chmod($destination_fichier,0604))
    		{
    			$up->exitStatusErreur(SetMessages::get('UpAbConfigChmod'));
    		}
     
    		// Si on arrive ici c'est que tout c'est bien passé, sinon les $up->exitStatusErreur() utilisés en cas d'erreur arrêtent le script et envoient le message correspondant. On pourrait donc enregistrer ici le(s) nom(s) du fichier en bdd. 
     
    		if($transfert)
    		{
    			// Si la variable $log_dossier_selection est définie on peut faire le log témoignant qu'un dossier sélectionné a été complété.
    			if(isset($log_dossier_selection))
    			{
    				// Log en utilisant $log_dossier_selection
    				// ...
    			}
     
     
    			/* 
    			J'enregistre les données dans des variables de session qui seront exploitées à la fin du traitement du formulaire. 
    			
    			Cette méthode est à réserver pour des informations visiteur plutôt que pour des traitemnts dont la défaillance pourrait perturber l'intégrité des données du site, car si une panne internet ou une coupure de courant survient avant la fin du traitement de tout le formulaire, on ne pourra pas utiliser les données enregistrées dans les variables de sessions puisque le tableau UpAbci_formEnd exploité plus loin pour récupérer ces données ne sera jamais reçu.
    			
    			Il est plus sécurisé de loguer les fichiers uploadés ici (dans la condition if($transfert)) les uns après les autres pour être certain de n'en manquer aucun. 
    			
    			$up->getParam("name") retourne le nom originel du fichier. J'utilise cette construction pour pouvoir récupérer facilement le nom du fichier nettoyé avec le tableau récapitulatif UpAbci_formEnd retourné en fin de traitment du formulaire.
    			*/
    			$ses_fichiers[$up->getParam("name")] = $nom_fichier_nettoye;
    		}		
    	}
    }
     
     
     
     
    /* 
    Si ET SEULEMENT SI on défini l'option "config.queryFormEnd = true" dans la configuration javascript du formulaire, une requête additionnelle est envoyée vers le serveur à la fin du traitement du formulaire. Elle contient les variables $_POST communes à tout le formulaire (non spécifiques à chaque fichier), et un tableau récapitulatif de l'upload pour chaque fichier récupérable avec la propriété "UpAbci_formEnd" de la classe php. 
    
    Si ce n'est pas la fin du traitement du formulaire ou si l'option javascript n'est pas configurée, $up->UpAbci_formEnd renvoie un tableau vide. Cf mode d'emploi "Configuration serveur -> Récupération des paramètres Ajax prédéfinis".
    */
    if(count($up->UpAbci_formEnd) > 0)
    {
    	// Ici on peut exploiter $ses_fichiers, $ses_dossier et $ses_new_dossier en pensant à les effacer à la fin du traitement pour éviter un conflit en cas d'envois successifs du formulaire.
     
    	// On peut vérifier que les fichiers ont été correctement transférés en testant l'index "result" qui doit retourner "ok_done".
    	$result = 0;
    	foreach($up->UpAbci_formEnd as $file)
    	{
    		if($file['result'] == "ok_done")
    		{
    			$result++;
     
    			/* 
    			pour info :
    			- le nom originel du fichier est $file['name']
    			- le nom du fichier nettoyé est donc $ses_fichiers[$file['name']] 
    			Attention : si vous souhaitez récupérer $ses_fichiers[$file['name']] en dehors de la condition if($file['result'] == "ok_done"), il faudra le tester avec "isset" car cet item n'est défini que pour les fichiers transférés (cf la construction de la variable de session $ses_fichiers plus haut à l'intérieur de la condition if ($transfert)).
    			*/
    		}
    	}
     
    	$message_debut = $result == count($up->UpAbci_formEnd) ? 'Toutes les photos ont bien été ajoutées dans l\'album. <br />' : 'Certaines photos n\'ont pas été ajoutées dans l\'album. Voir le détail dans la liste ci-dessous.<br />';
     
    	// Le message de création d'un nouveau dossier sera envoyé pour chaque envoi du formulaire (tant que l'utilisateur n'a pas rafraichi sa page même s'il utilise le même dossier) en testant $ses_new_dossier, ou il sera envoyé une seule fois tant que l'utilisateur ne rafrachi pas sa page et s'il utilise le même dossier, en testant $ses_new_dossier_message. Car ces deux variables ne sont pas supprimées au même moment, voir leur construction avec sesInit.
    	$message_creation_successifs = false;
     
    	$message_new_dossier = $message_creation_successifs ? $ses_new_dossier == $new_dossier_name_post : $ses_new_dossier_message == $new_dossier_name_post;
     
    	// Je construis un message différent si un nouveau répertoire a été créé ou non.
    	// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    	$message = $message_new_dossier ? 
    	$message_debut.'Adresse du nouvel album : <a target="_blank" href="../../photos/'.htmlspecialchars($ses_dossier).'/">https://'.$_SERVER['HTTP_HOST'].'/photos/'.htmlspecialchars($ses_dossier).'/</a> <br /><span style="color: red; font-weight: bold;">/!\ Il est important de rajouter l\'adresse de l\'album dans la page "Album" du site. <a href="../contenus/edit?id=18">Cliquez ici pour le faire après avoir copié l\'adresse de l\'album ci-dessus </a> /!\</span>'
    	:
    	$message_debut;
     
    	$message = '<div style="border:2px solid #F90;color:black;padding:0.5em;margin-top:1em">'.$message.'</div>';
     
     
    	// Envoi du message dans l'élément html ayant la classe UpAbci_infosServer
    	$up->addInfosServer($message);
     
    	// Envoi du tableau pour la mise à jour du select
    	if (isset($ses_new_select)){$up->addMixteServer($ses_new_select);}
     
    	// Ne pas oublier de supprimer les variables de session en fin de traitement du formulaire
    	unsetSesInit($uniqid_form);
     
     
    	// Pour voir facilement le contenu de UpAbci_formEnd en phase de développement (sera affiché dans l'élément html ayant la classe UpAbci_infosServer)
    	/*
    	ob_start();
    	echo '<pre>'.var_dump($up->UpAbci_formEnd).'</pre>';
    	$dump = ob_get_contents();
    	ob_end_clean();
    	$up->addInfosServer($dump);
    	*/
     
    }
    $up->exitReponseAjax();
    ?>

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    <script>
    "use strict"; // Vous pouvez supprimer cette ligne en cas d'utilisation d'autres scripts javascript qui ne supportent pas ce mode.
     
     
    // Initialisation de la classe javascript (identifiant formulaire, destination ajax, identifiant réponse)
    $(function(){
     
    var form_album = $("#form_redim");
    var reponse_upload = $("#reponse_upload");
     
    var dossier_name = form_album.find('.ctrldos').find("select");
    var new_dossier_name = form_album.find('.ctrldos').find("input[type=text]");
     
    // Pour ne pas permettre à la fois une sélection d'album (dossier) et avoir le champ text nouvel album rempli
    dossier_name.on("change",function()
    {
    	if(new_dossier_name.val()!='') {
    		$(this).find('option[value=""]').prop('selected', true);
    	}
    	else if($(this).val()=="") {
    		new_dossier_name.attr("disabled",false);
    	}
    	else {
    		new_dossier_name.attr("disabled",true);
    	}
    })
     
     
    // On enregistre les valeurs des options du select pour les comparer onsubmit à la valeur du champ nouvel album et envoyer un message en conséquence.
    var tab_select = [];
    dossier_name.find('option').each(function(i,v){
    		tab_select.push($(this).val());
    })
     
    // Utilisé pour pouvoir ajouter d'autres fichiers au dernier dossier nouvellement créé sans avoir le message d'alerte
    var new_dossier_name_post;
     
     
     
    // Destination ajax de l'upload
    var destination_ajax = 'Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php';
     
    var up = new UploadAjaxABCI(destination_ajax, form_album, reponse_upload);
     
    // Met les champs input en readonly durant le téléchargement des fichiers (attention, readonly n'est pas pris en compte par tous les input, voir paragraphe "Configuration javascript optionnelle" dans le fichier UploadAjaxABCI_Champs_Sup_Notation.php)
    up.config.inputFormAttrOnSubmit = "readonly";
     
    // Envoi une requête de fin de traitement de formulaire vers le serveur
    up.config.queryFormEnd = true;
     
    // Interdit la soumission du formulaire sans fichiers joints 
    up.config.submitWithoutFile = false;
     
    // Option pour indiquer un élément html en remplacement du bouton de sélection des fichiers par défaut du navigateur.
    up.config.customFileSelect = ".bouton_custom_file";
     
    // Extensions autorisées
    up.config.filesExtensions = ['jpg','jpeg','png','gif'];
     
    // S'affichera si le redimensionnement et l'upload sont ok.
    up.info.status.ok = "Upload et redimensionnements OK";
     
    // Message d'erreur si problème serveur. Sera complété par le message renvoyé par le serveur pour plus de précision.
    up.info.status.errorServer = "Echec du traitement. ";
     
    up.config.imgPreviewMaxSizeTotal = 200; // en Mo poids total maximum de toutes les photos. Au delà les vignettes ne seront pas affichées.
     
    up.config.imgPreviewMaxWidth = 100; // en pixels, largeur maximale de l'aperçu
    up.config.imgPreviewMaxHeight = 100;// en pixels, hauteur maximale de l'aperçu
     
    // Pour compenser bug sur Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1434496. On utilise FileReader pour la prévisualisation des vignettes, uniquement pour firefox car cette option est gourmande en ressources.
    if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
    	up.config.imgPreviewUseFileReader = true;
    }
     
     
    // La fonction config.func_onFormSubmit (si définie) permet d'intercepter et d'interrompre la soumission du formulaire
    up.config.func_onFormSubmit = function(event,tableau){
    	var erreur = false;
     
    	var message;
    	var message_debut;
    	var message_form = form_album.find(".erreurs_form");
    	var new_dossier_name_val = $.trim(new_dossier_name.val());
     
    	// Contrôle de la validité du formulaire
    	if($.trim(dossier_name.val()) == '' && new_dossier_name_val == ''){
    		erreur = true;
    		message = "Vous n'avez choisi aucune option pour l'album. Merci d'en choisir une.";	
    	}
    	else if(new_dossier_name_val != '')
    	{
    		// Il faut nettoyer le nom du dossier saisi avec la même fonction que celle utilisée côté serveur pour pouvoir le comparer et le rejeter s'il a le même nom après correction qu'un dossier déjà existant.
    		var new_dossier_nettoye = cleanDossier(new_dossier_name_val);
    		// la condition new_dossier_name_post != new_dossier_nettoye est utilisée pour autoriser la mise à jour d'un nouvel album dernièrement créé. 
    		if($.inArray(new_dossier_nettoye, tab_select) != -1 && new_dossier_name_post != new_dossier_nettoye) 
    		{
    			erreur = true;
     
    			message_debut = 'Le nouvel album "'+new_dossier_name_val+'" ';
    			message = new_dossier_nettoye != new_dossier_name_val ? message_debut+'renommé "'+new_dossier_nettoye.replace(/-/g,' ')+'" après remplacement des caractères non valides ' : message_debut;
    			message += "existe déjà. Utilisez le sélecteur d'album pour compléter un album existant.";
     
    			// On vide le champ
    			new_dossier_name.val('');
    		}
    	}
     
    	if (erreur) {
    		message_form.html(message);
    		// Fait afficher le message d'erreur avec un effet slide
    		message_form.slideDown(150);
    	}
    	else {
    		// Ferme le message avec un effet slide
    		message_form.slideUp(150);
     
    		// Pour soumettre l'envoi du formulaire interrompu par la fonction config.func_onFormSubmit
    		up.func_SubmitForm();
    	}
    }
     
     
    /* La fonction config.func_FormEnd est exécutée (si définie) à la fin du traitement du formulaire. 
    Je m'en sert ici pour fermer le bloc d'information des fichiers si l'envoi du formulaire a été annulé, en fonction de la valeur de mixte_serveur définie en php avec la méthode addMixteServer. 
    Dans l'exemple de code php, mixte_serveur est utilisé lors du retour des erreurs serveurs pour signaler que le traitement du formulaire a été annulé. On pourrait en faire une toute autre utilisation et notez par ailleurs que mixte_serveur peut accepter tout type de contenu, texte, html ou tableau php qui sera converti automatiquement en objet javascript.
    */
    up.config.func_FormEnd = function(tableau, info_serveur, mixte_serveur){
     
    	if(mixte_serveur == 'annule') {
    		reponse_upload.slideUp(150);
    	}
    	else if(typeof mixte_serveur == "object") // Si mixte_serveur est un objet c'est que l'on a retourné un nouveau dossier qui vient d'être créé
    	{
    		$.each(mixte_serveur,function(i,v)
    		{
    			// On alimente le tableau de comparaison
    			tab_select.push(i);
     
    			// Et on ajoute cet élément dans le sélecteur html. eq(0) pour insérer juste après la première valeur vide ayant le label "choisissez"
    			$('<option value="'+i+'">'+v+'</option>').insertAfter(dossier_name.find('option').eq(0));	
     
    			// Enregistrement du dernier dossier créé
    			new_dossier_name_post = i;
    		})
    	}
    }
     
    // Démarrage de la fonction, DOM chargé
    up.Start();
     
     
     
    // Copie de la fonction "cleanDossier" (qui utilise la fonction "cleanFileName" cf "Php_Upload/Classes/UploadABCIServices.php" côté serveur) et traduite en javascript
    var cleanDossier = function (dossier)
    {
    	var cible = [
    		'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ă', 'Ą',
    		'Ç', 'Ć', 'Č', 'Œ',
    		'Ď', 'Đ',
    		'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ă', 'ą',
    		'ç', 'ć', 'č', 'œ',
    		'ď', 'đ',
    		'È', 'É', 'Ê', 'Ë', 'Ę', 'Ě',
    		'Ğ',
    		'Ì', 'Í', 'Î', 'Ï', 'İ',
    		'Ĺ', 'Ľ', 'Ł',
    		'è', 'é', 'ê', 'ë', 'ę', 'ě',
    		'ğ',
    		'ì', 'í', 'î', 'ï', 'ı',
    		'ĺ', 'ľ', 'ł',
    		'Ñ', 'Ń', 'Ň',
    		'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ő',
    		'Ŕ', 'Ř',
    		'Ś', 'Ş', 'Š',
    		'ñ', 'ń', 'ň',
    		'ò', 'ó', 'ô', 'ö', 'ø', 'ő',
    		'ŕ', 'ř',
    		'ś', 'ş', 'š',
    		'Ţ', 'Ť',
    		'Ù', 'Ú', 'Û', 'Ų', 'Ü', 'Ů', 'Ű',
    		'Ý', 'ß',
    		'Ź', 'Ż', 'Ž',
    		'ţ', 'ť',
    		'ù', 'ú', 'û', 'ų', 'ü', 'ů', 'ű',
    		'ý', 'ÿ',
    		'ź', 'ż', 'ž',
    		'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р',
    		'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'р',
    		'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
    		'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я'
    		];
     
    	var rempl = [
    		'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'A', 'A',
    		'C', 'C', 'C', 'CE',
    		'D', 'D',
    		'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'a', 'a',
    		'c', 'c', 'c', 'ce',
    		'd', 'd',
    		'E', 'E', 'E', 'E', 'E', 'E',
    		'G',
    		'I', 'I', 'I', 'I', 'I',
    		'L', 'L', 'L',
    		'e', 'e', 'e', 'e', 'e', 'e',
    		'g',
    		'i', 'i', 'i', 'i', 'i',
    		'l', 'l', 'l',
    		'N', 'N', 'N',
    		'O', 'O', 'O', 'O', 'O', 'O', 'O',
    		'R', 'R',
    		'S', 'S', 'S',
    		'n', 'n', 'n',
    		'o', 'o', 'o', 'o', 'o', 'o',
    		'r', 'r',
    		's', 's', 's',
    		'T', 'T',
    		'U', 'U', 'U', 'U', 'U', 'U', 'U',
    		'Y', 'Y',
    		'Z', 'Z', 'Z',
    		't', 't',
    		'u', 'u', 'u', 'u', 'u', 'u', 'u',
    		'y', 'y',
    		'z', 'z', 'z',
    		'A', 'B', 'B', 'r', 'A', 'E', 'E', 'X', '3', 'N', 'N', 'K', 'N', 'M', 'H', 'O', 'N', 'P',
    		'a', 'b', 'b', 'r', 'a', 'e', 'e', 'x', '3', 'n', 'n', 'k', 'n', 'm', 'h', 'o', 'p',
    		'C', 'T', 'Y', 'O', 'X', 'U', 'u', 'W', 'W', 'b', 'b', 'b', 'E', 'O', 'R',
    		'c', 't', 'y', 'o', 'x', 'u', 'u', 'w', 'w', 'b', 'b', 'b', 'e', 'o', 'r'
    		];
     
    	var regex;
    	var text = dossier;
    	// Avant d'appliquer la fonction "cleanFileName" côté serveur - fichier "Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php"- on supprime (pour cette application) les séparateurs de dossiers et les points. On refait donc la même chose ici.
    	regex = new RegExp('[/.]', "g");
    	text = text.replace(regex, '');
     
    	$.each(cible,function(i,v)
    	{
    		regex = new RegExp(v, "g");
    		text = text.replace(regex,rempl[i]);
    	});
     
    	text = text.replace(/[^.a-z0-9_-]/gi, '-');
    	text = text.replace(/-{2,}/,'-',text);
    	text = dossier.lastIndexOf('-',dossier.length-1) != -1 ? text : text.replace(/-+$/,'');
     
    	return text;
    }
    })
    </script>
    Le tarif est de cliquer sur le pouce vert dans la page de téléchargement du module ici.
    Cela permettra d'indiquer que ce module d'upload fonctionne, contrairement au compteur de téléchargement de ce site qui est en panne (il diminue régulièrement alors qu'au pire il ne devrait pas augmenter : près de 1600 téléchargements il y a deux mois, contre 1500 environ aujourd'hui ).
    Cela compensera un peu

    EDIT : Je viens de compléter le code et je m'aperçois que le tableau nommé "cible" tout en bas du code javascript ne ressort pas bien. Si cela pose problème copie le tableau "cible" depuis le fichier php (indiqué en commentaire au dessus de cleanDossier) et remplace le tableau javascript du même nom sans toucher au reste.

  6. #186
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Bonjour,

    Cela fonctionne maintenant ! Un grand grand grand merci en tout cas !

    J'aurais cliqué avec plaisir sur le pouce vert en guise de remerciements mais hélas il ne fonctionne pas non plus
    Il n'y a aucun effet au clic ! Désolé

    Bon weekend

  7. #187
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juin 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 16
    Points : 22
    Points
    22
    Par défaut gif animé
    hello

    J'utilise ABCIWEB pour le transfert d'image dans le cadre d'un diaporama.
    est il possible d'envoyer des gif animé sans en perdre justement l'animation ?

    Merci

  8. #188
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Citation Envoyé par D333x Voir le message
    Bonjour,

    Cela fonctionne maintenant ! Un grand grand grand merci en tout cas !

    J'aurais cliqué avec plaisir sur le pouce vert en guise de remerciements mais hélas il ne fonctionne pas non plus
    Il n'y a aucun effet au clic ! Désolé

    Bon weekend
    Décidément, pas facile d'avoir un retour d'après les notations de la rubrique téléchargement de ce site puisque le compteur de téléchargement est en rade et les appréciations également

    Enfin bon, c'était juste un mot pour te dire qu'il manquait encore deux petites lignes pour être complet dans le code javascript de mon exemple précédent : j'ai fais l'équivalent de la fonction de nettoyage php en javascript pour comparer des noms de dossiers comparables côté client et côté serveur, mais j'avais oublié que je supprimais les points et les séparateurs de dossiers avant d'utiliser cette fonction. Il faut donc faire de même, ce que tu peux retrouver maintenant dans mon code précédent (édité) après le commentaire :
    // Avant d'appliquer la fonction cleanFileName côté serveur - fichier "Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php" - on supprime (pour cette application) les séparateurs de dossiers et les points. On refait donc la même chose ici.
    Voilà

    (T'as de la chance, j'ai repensé à ce code parce qu'il est intéressant pour montrer certaines possibilités et je l'intégrerai dans mes fichiers d'exemples pour la prochaine version. Cela dit, cet oubli avait des conséquences très marginales et de toutes façons le contrôle de sécurité côté serveur aurait traité le problème).

  9. #189
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Citation Envoyé par astuces72 Voir le message
    hello

    J'utilise ABCIWEB pour le transfert d'image dans le cadre d'un diaporama.
    est il possible d'envoyer des gif animé sans en perdre justement l'animation ?

    Merci
    Les fichiers sont transférés tels qu'ils sont, la classe d'upload ne les modifie pas (sauf si tu appliques des traitements particuliers), donc bien entendu que tu peux transférer un gif animé de même que n'importe quel fichier quel qu'il soit.

    Tu as un problème particulier ?

  10. #190
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Bonjour,

    Ci-dessous un script finalisé qui reprend et corrige l'exemple précédent et qui sera proposé dans la prochaine version du module d'upload.

    Note : J'utilise dans ce message un formatage spécial pour rendre certains caractères compatibles avec le système d'affichage de ce site. La coloration syntaxique est donc inopérante, de même que le lien "Visualiser dans une fenêtre à part" ne respecte pas tous les caractères. Utilisez le lien "Selectionner tout" qui reste fonctionnel et vous permettra de copier fidèlement tous les caractères du code.

    Formulaire "UploadAjaxABCI_Redimensions_Album.php"
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    <?php
    /* 
    Utilise le fichier "Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php" comme destination Ajax
    */
    session_start();
    header('Content-type: text/html; charset=UTF-8');// Inutile depuis php 5.6
     
    // Charge les classes php avec spl_autoload_register
    spl_autoload_register(function ($class) {require 'Php_Upload/Classes/' . $class . '.php';});
     
    $up = new UploadABCIServices();
     
    $UpAbci_fragmentSize = $up->returnOctets('8M');
     
    // Vérifie si $UpAbci_fragmentSize n'est pas supérieur aux limites du serveur
    $upload_max_filesize = min($up->returnOctets(ini_get('upload_max_filesize')), $up->returnOctets(ini_get('post_max_size')));$UpAbci_fragmentSize = !empty($UpAbci_fragmentSize) && $upload_max_filesize > $UpAbci_fragmentSize ? $UpAbci_fragmentSize : $upload_max_filesize;
     
    // Génère un identifiant unique à chaque rafraichissement de la page
    $UpAbci_uniqidForm = $up->getUniqid();
     
    // Jeton de formulaire (token);
    $_SESSION['UploadAjaxABCI'][$UpAbci_uniqidForm]['token'] = 1;
     
     
    // Pour alimenter le select des dossiers/albums existant
    $repertoire_destination = 'Album_Photo/';
     
    $tab_dos = [];
    $erreur_dossier = null;
    try
    {
            $iterator = new DirectoryIterator($repertoire_destination);
            foreach ($iterator as $fileinfo) 
            {
                    if ($fileinfo->isDir() && !$fileinfo->isDot()) 
                    {
                            $tab_dos[] = $fileinfo->getFilename();
                    }
            }
    }
    catch (Exception $e)
    {
             $erreur_dossier = '<div style="border:3px solid red;border-radius:5px;margin-top:2em;color:red;padding:0.5em">Le dossier "'.htmlspecialchars($repertoire_destination).'" est introuvable. Il sera créé automatiquement dans le même répertoire que ce formulaire (si les droits du répertoire le permettent), dès la création d\'un nouvel album.</div>';
    }
     
    sort($tab_dos);
     
    $options = null;
    foreach ($tab_dos as $value)
            $options .= '<option value="'.$value.'">'.str_replace('_',' ',$value).'</option>'."\n";
    ?>
    <!DOCTYPE html>
    <html lang="fr">
    <head>
    <meta charset="UTF-8">
    <meta name=viewport content="width=device-width, initial-scale=1">
     
    <title>Album photo Upload Ajax ABCIWEB</title>
    <link rel="icon" type="image/png" href="Javascript/Images/favicon.png">
     
    <style type="text/css">
    p {
            padding:0;
            margin:0;
    }
     
    .UpAbci_infosFile {
            word-wrap:break-word;   
    }
     
    .UpAbci_infosFile progress {
            width:100px;
    }
    </style>
    </head>
    <body style="font-family:Arial, Helvetica, sans-serif; font-size:0.9em;max-width:850px;margin:3em auto 0 auto;line-height:1.8em">
    <h3 style="margin:2em auto;font-family:Arial, Helvetica, sans-serif; font-size:1.4em;">
    Création et mise à jour d'albums photo
    </h3>
    <div>
    Les photos sont redimensionnées en deux formats et enregistrées dans des dossiers/albums que l'utilisateur peut créer et compléter depuis ce formulaire. Le nom de l'album est utilisé comme nom de dossier après avoir remplacé ou supprimé les caractères spéciaux.<br><br>
     
    <br>
     
    <strong>Côté client</strong><br>
    La difficulté et l'intérêt de cet exemple côté javascript est de permettre de compléter un album dernièrement créé sans avoir besoin d'utiliser le sélecteur de dossier, tout en affichant un message d'erreur si le visiteur saisi le nom d'un album existant pour créer un nouvel album. On se servira des retours serveurs pour mettre à jour le tableau de comparaison des albums existants, ainsi que pour la mise à jour des options html du select.<br>
     
    - Interception de l'événement onSubmit et contrôles avant l'envoi du formulaire.<br>
    - Gestion des messages d'erreurs.<br>
    - Mise à jour du tableau de comparaison des dossiers et du sélecteur d'album en fonction des albums nouvellement créés en retour d'information serveur.<br>
     
    Notez (cf. autres exemples de formulaires) que la fonction "config.func_FormEnd" est toujours disponible côté javascript, indépendamment de la configuration de l'option "config.queryFormEnd" qui est utilisée pour envoyer une requête additionnelle contenant un tableau récapitulatif vers le serveur à la fin du traitement du formulaire .<br><br>
     
    <strong>Côté serveur</strong><br>
    (voir le fichier "Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php")<br>
    Cet exemple montre l'utilisation de variables de sessions dépendantes du formulaire, qui seront définies pour la session entière, ou pour plusieurs téléchargements successifs tant que l'utilisateur n'a pas rafraichi la page du formulaire, ou pour le téléchargement en cours. <br>
    - Elles sont utilisées pour envoyer en temps voulu des messages appropriés avec la méthode "addInfosServer()" en fonction de la création ou de la mise à jour d'album, ainsi que pour faire des log. <br>
    - La méthode "addMixteServer()" est utilisée conjointement pour retourner (entre autre) un tableau contenant l'album dernièrement créé, récupérable dans le troisième paramètre de la fonction javascript événementielle "config.func_FormEnd", et qui sera utilisé pour mettre à jour les options html du selecteur d'album.<br>
    - Une fonction "stopFormExit()" est créée pour annuler le traitement du formulaire en cas d'erreur de dossier et retourner un message correspondant.<br>
    - Le code php fait les mêmes contrôles que javascript pour sécuriser le script.
    <br><br>
     
    <strong>Noter</strong> qu'il convient de ne pas faire de log ou d'enregistrements importants dont la défaillance pourrait perturber l'intégrité des données du site à l'intérieur de la condition "if(count($up->UpAbci_formEnd) > 0)" car le tableau retourné n'est renseigné que par la requête additionelle envoyée à la fin du traitement du formulaire (uniquement si l'option javascript "config.queryFormEnd" = true). En cas de panne internet, le script pourrait être stoppé durant le traitement avant l'envoi de cette dernière requête et dans cette hytpothèse certains fichiers pourraient être traités sans que l'on puisse les loger.<br>
     L'endroit le plus sécurisé pour faire des log se situe donc la plupart du temps dans la condition "if($transfert)", dès que le fichier est correctement transféré.<br>
    <br>
     
     
     
    </div>
    <?= $erreur_dossier ?>
    <div style="margin:2em 0">
    <form id="form_redim" action="#" method="post">
     <fieldset style="border:3px solid #C5C5C5;border-radius:5px;padding:1em 1em 1.5em 1em;">
        <legend style="font-size:large">Album Photo </legend>
         <input type="hidden" name="UpAbci_fragmentSize" value="<?=$UpAbci_fragmentSize?>">
         <input type="hidden" name="UpAbci_uniqidForm" value="<?=$UpAbci_uniqidForm?>">
         <input type="file" name="upload" multiple="multiple" style="display:none">
     
     
         <p class="ctrldos">
         <label>Choisir un album existant&nbsp;
         <select name="dossier_name">
             <option value="">Choisissez...</option>
             <?= $options?>
         </select></label>
    	 <strong>&nbsp;&nbsp;OU&nbsp;&nbsp;</strong>
         <label>Indiquer un nouvel album&nbsp;<input type="text" name="new_dossier_name" placeholder="Nom du nouvel album"></label>
         </p>
     
         <p style="margin-top:2em">
         <input type="button" class="bouton_custom_file" value="Cliquez ou déposez vos fichiers ici" style="width:300px;height:40px;font-weight:bold;text-align:center;">
     
    	<!-- Pour éviter une fausse manip à l'utilisateur, inutile de proposer le bouton "envoyer" tant que des fichiers non traités n'ont pas été sélectionnés. Les styles événementiels "data-upabcicss-select-file" et "data-upabcicss-form-end" permettent de gérer cette condition -->
         <input type="submit" value="Envoyer" style="display:none;color:green;width:100px;height:40px;font-weight:bold;margin-left:2em" data-upabcicss-select-file="display:inline-block" data-upabcicss-form-end="display:none">
         </p>
     
         <!-- Bloc conteneur retour d'informations générales du serveur. J'utilise le style événementiel "data-upabcicss-select-file" pour le cacher dès la sélection de nouveaux fichiers. Il sera affiché par "data-upabcicss-infos-server" qui est déclenché lors du retour serveur si l'on a utilisé la méthode "addInfosServer()" côté serveur -->
         <div class="UpAbci_infosServer" style="display:none" data-upabcicss-submit="display:none" data-upabcicss-select-file="display:none" data-upabcicss-infos-server="display:block"></div>
     
         <!-- Bloc conteneur retour d'informations générales du contrôle javascript. J'utilise les styles événementiels data-upabcicss-select-file et data-upabcicss-submit pour supprimer cet affichage à la sélection des fichiers et à la soumission du formulaire -->
         <p class="erreurs_form" style="display:none;border:3px solid red;border-radius:5px;color:red;padding:0.5em;margin-top:1em" data-upabcicss-select-file="display:none" data-upabcicss-submit="display:none"></p>
     
         <!-- Bloc conteneur du retour d'informations spécifiques au fichiers -->
         <div id="reponse_upload" data-upabcicss-select-file="display:block" style="margin-top:2em;">
     
            <!--information du fichier que l'on affiche uniquement si un fichier est sélectionné, pour éviter la barre de progression graphique vide si soumission du formulaire sans fichier (c'est une précaution générique mais qui ne peut pas arriver ici puisqu'il est impossible dans cet exemple de soumettre le formulaire sans fichier joint)-->
             <div class="UpAbci_infosFile" style="display:none;margin-top:1em;clear:both" data-upabcicss-select-file="display:block;">
            	 <hr>
                 <div>
                	 <!-- vignettes si le poids total ne dépasse pas la config javascript définie plus bas à 100Mo  -->
                     <p class="UpAbci_imgPreview" style="float:right"></p>
     
                    <p>
                    <!-- bouton stop -->
                    <span class="UpAbci_stop" style="color:red;cursor:pointer;font-size:0.8em;" data-upabcicss-result="cursor:default;opacity:0.5;color:#666">stop</span>&nbsp;
                  	<!-- nom du fichier -->
                    <span class="UpAbci_name"></span>
                    <!-- progression graphique -->
                    <progress class="UpAbci_progressionG"></progress>
                    <!-- status (important sinon pas de retour d'information en cas d'erreur de traitement du fichier) --> 
                    <span class="UpAbci_status" data-upabcicss-result-ok="color:green;font-weight:bold">en attente</span>
                    </p>
                </div>
     
                <!-- S'affichera si une sauvegarde existe en cas d'arrêt ou d'erreur -->
                <p style="display:none;" data-upabcicss-result-partial="display:block">- sauvegardé : <span class="UpAbci_backup">0 Mo</span></p>
     
             </div>
        </div>
     </fieldset>
    </form>
    </div>
     
    <p style="margin-top:3em;margin-bottom:3em"><a href="index.html#fichiers_exemples">Index</a></p>
     
    </body>
     
    <script src="Javascript/jquery.js"></script>
    <script src="Javascript/UploadAjaxABCI.js"></script>
     
    <script>
    "use strict"; // Vous pouvez supprimer cette ligne en cas d'utilisation d'autres scripts javascript qui ne supportent pas ce mode.
     
     
    $(function(){
     
    var form_album = $("#form_redim");
    var reponse_upload = $("#reponse_upload");
     
    var dossier_name = form_album.find('.ctrldos').find("select");
    var new_dossier_name = form_album.find('.ctrldos').find("input[type=text]");
     
    // Pour ne pas permettre à la fois une sélection d'album (dossier) et avoir le champ text nouvel album rempli
    dossier_name.on("change",function()
    {
            if($(this).val()=="") {
                    new_dossier_name.attr("disabled",false);
            }
            else {
                    new_dossier_name.attr("disabled",true);
            }
    })
     
     
    // On enregistre les valeurs des options du select pour les comparer onsubmit à la valeur du champ nouvel album et envoyer un message en conséquence.
    var tab_select = [];
    dossier_name.find('option').each(function(i,v){
                    tab_select.push($(this).val());
    })
     
    // Utilisé pour pouvoir ajouter d'autres fichiers au dernier dossier nouvellement créé sans avoir le message d'alerte
    var new_dossier_serveur;
    var new_dossier_name_val_ex;
     
     
    // Destination ajax de l'upload
    var destination_ajax = 'Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php';
     
    // Initialisation de la classe javascript (destination ajax, identifiant formulaire, identifiant réponse)
    var up = new UploadAjaxABCI(destination_ajax, form_album, reponse_upload);
     
    // Met les champs input en readonly durant le téléchargement des fichiers (attention, readonly n'est pas pris en compte par tous les input, voir paragraphe "Configuration javascript optionnelle" dans le fichier UploadAjaxABCI_Champs_Sup_Notation.php)
    up.config.inputFormAttrOnSubmit = "readonly";
     
    // Envoi une requête additionnelle de fin de traitement du formulaire vers le serveur
    up.config.queryFormEnd = true;
     
    // Interdit la soumission du formulaire sans fichiers joints 
    up.config.submitWithoutFile = false;
     
    // Option pour indiquer un élément html en remplacement du bouton de sélection des fichiers par défaut du navigateur.
    up.config.customFileSelect = ".bouton_custom_file";
     
    // Extensions autorisées
    up.config.filesExtensions = ['jpg','jpeg','png','gif'];
     
    // S'affichera si le redimensionnement et l'upload sont ok.
    up.info.status.ok = "Upload et redimensionnements OK";
     
    // Message d'erreur si problème serveur. Sera complété par le message renvoyé par le serveur pour plus de précision.
    up.info.status.errorServer = "Echec du traitement. ";
     
    up.config.imgPreviewMaxSizeTotal = 200; // en Mo poids total maximum de toutes les photos. Au delà les vignettes ne seront pas affichées.
     
    up.config.imgPreviewMaxWidth = 100; // en pixels, largeur maximale de l'aperçu
    up.config.imgPreviewMaxHeight = 100;// en pixels, hauteur maximale de l'aperçu
     
    // Pour compenser bug sur Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1434496. On utilise FileReader pour la prévisualisation des vignettes, uniquement pour firefox car cette option est gourmande en ressources.
    if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
            up.config.imgPreviewUseFileReader = true;
    }
     
     
    // La fonction config.func_onFormSubmit (si définie) permet d'intercepter et d'interrompre la soumission du formulaire
    up.config.func_onFormSubmit = function(event,tableau){
            var erreur = false;
            
            var message_form = form_album.find(".erreurs_form");
            var new_dossier_name_val = $.trim(new_dossier_name.val());
            
            var message, message_debut;
            
            // Contrôle de la validité du formulaire
            if($.trim(dossier_name.val()) == '' && new_dossier_name_val == ''){
                    erreur = true;
                    message = "Vous n'avez choisi aucune option pour l'album. Merci d'en choisir une.";     
            }
            else if(new_dossier_name_val != '')
            {
                    // Il faut nettoyer le nom du dossier saisi avec la même fonction que celle utilisée côté serveur pour pouvoir le comparer et le rejeter s'il a le même nom après correction qu'un dossier déjà existant.
                    var new_dossier_nettoye = cleanDossier(new_dossier_name_val);
                    
                    if(new_dossier_nettoye == '')
                    {
                            erreur = true;
                            message = 'Le nom d\'album "'+new_dossier_name_val+'" n\'est pas valide.';
                    }
                    else
                    
                    /* 
                    Si le nom du nouveau dossier est inclus dans le tableau des fichiers existants et que ce n'est pas le dernier créé on envoie un message d'erreur.
                    new_dossier_serveur != new_dossier_nettoye pour autoriser la mise à jour d'un nouvel album dernièrement créé sans entrer dans la condition d'erreur. 
                    
                    La deuxième condition est pour déclencher le message d'erreur si l'utilisateur saisi successivement deux noms
    différents mais qui sont indentiques après nettoyage. 
                    */
                    if(($.inArray(new_dossier_nettoye, tab_select) != -1 && new_dossier_serveur != new_dossier_nettoye) || (new_dossier_serveur == new_dossier_nettoye && new_dossier_name_val_ex != undefined && new_dossier_name_val != new_dossier_name_val_ex))
                    {
                            erreur = true;
     
                            // Pour l'affichage on remplace les _ par des espaces                   
                            message_debut = 'Le nouvel album "'+new_dossier_name_val+'" ';
                            message = new_dossier_nettoye != new_dossier_name_val.replace(/ /g,'_') ? message_debut+', renommé "'+new_dossier_nettoye.replace(/_/g,' ')+'" après remplacement des caractères non valides, ' : message_debut;
                            message += "existe déjà. Utilisez le sélecteur d'album pour compléter un album existant.";
                            
                            // On vide le champ
                            new_dossier_name.val('');
                    }       
                    
                    new_dossier_name_val_ex = new_dossier_name_val;
            }
            
            if (erreur) {
                    // On utilise la méthode jQuery "text()" plutôt que la méthode "html()" pour éviter une rupture de chaine si le texte contient des balises html ('<' par exemple) 
                    message_form.text(message);
                    // Fait afficher le message d'erreur avec un effet slide
                    message_form.slideDown(150);
            }
            else {
                    // Ferme le message avec un effet slide
                    message_form.slideUp(150);
                    
                    // Pour soumettre l'envoi du formulaire interrompu par la fonction config.func_onFormSubmit
                    up.func_SubmitForm();
            }
    }
     
     
    /* La fonction config.func_FormEnd est exécutée (si définie) à la fin du traitement du formulaire. 
    En fonction de la valeur de mixte_serveur définie en php avec la méthode addMixteServer, je m'en sert ici pour fermer le bloc d'information des fichiers si l'envoi du formulaire a été annulé,  
    ou,
    pour alimenter le tableau qui enregistre les valeurs du select et pour mettre à jour les options dans le html du select.
    */
    up.config.func_FormEnd = function(tableau, info_serveur, mixte_serveur){
            
            if(mixte_serveur == 'annule') {
                    reponse_upload.slideUp(150);
            }
            else if(typeof mixte_serveur == "object") // Si mixte_serveur est un objet c'est que l'on a retourné un nouveau dossier qui vient d'être créé sous forme de tableau.
            {
                    // Mixte serveur est ici un tableau associatif contenant un seul élément
                    $.each(mixte_serveur,function(i,v) {
                            // On alimente le tableau de comparaison
                            tab_select.push(i);
                            
                            // Et on ajoute cet élément dans le sélecteur html. eq(0) pour insérer juste après la première valeur vide ayant le label "choisissez"
                            $('<option value="'+i+'">'+v+'</option>').insertAfter(dossier_name.find('option').eq(0));       
                            
                            // Enregistrement du dernier dossier créé
                            new_dossier_serveur = i;
                    })
            }
    }
     
    // Démarrage de la fonction, DOM chargé
    up.Start();
     
     
     
    // Copie de la fonction "cleanDossier()" définie dans le script d'upload côté serveur, voir le fichier 'Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php'. 
    var cleanDossier = function (dossier)
    {
            // Il faut échapper le point avec \\ car on utilise un regex en javascript pour faire le remplacement
            var cible = [
                    ' ', '/', '\\.',
                    'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ă', 'Ą',
                    'Ç', 'Ć', 'Č', 'Œ',
                    'Ď', 'Đ',
                    'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ă', 'ą',
                    'ç', 'ć', 'č', 'œ',
                    'ď', 'đ',
                    'È', 'É', 'Ê', 'Ë', 'Ę', 'Ě',
                    'Ğ',
                    'Ì', 'Í', 'Î', 'Ï', 'İ',
                    'Ĺ', 'Ľ', 'Ł',
                    'è', 'é', 'ê', 'ë', 'ę', 'ě',
                    'ğ',
                    'ì', 'í', 'î', 'ï', 'ı',
                    'ĺ', 'ľ', 'ł',
                    'Ñ', 'Ń', 'Ň',
                    'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ő',
                    'Ŕ', 'Ř',
                    'Ś', 'Ş', 'Š',
                    'ñ', 'ń', 'ň',
                    'ò', 'ó', 'ô', 'ö', 'ø', 'ő',
                    'ŕ', 'ř',
                    'ś', 'ş', 'š',
                    'Ţ', 'Ť',
                    'Ù', 'Ú', 'Û', 'Ų', 'Ü', 'Ů', 'Ű',
                    'Ý', 'ß',
                    'Ź', 'Ż', 'Ž',
                    'ţ', 'ť',
                    'ù', 'ú', 'û', 'ų', 'ü', 'ů', 'ű',
                    'ý', 'ÿ',
                    'ź', 'ż', 'ž',
                    'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р',
                    'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'р',
                    'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
                    'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я'
                    ];
                                             
            var rempl = [
                    '_', '', '',
                    'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'A', 'A',
                    'C', 'C', 'C', 'CE',
                    'D', 'D',
                    'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'a', 'a',
                    'c', 'c', 'c', 'ce',
                    'd', 'd',
                    'E', 'E', 'E', 'E', 'E', 'E',
                    'G',
                    'I', 'I', 'I', 'I', 'I',
                    'L', 'L', 'L',
                    'e', 'e', 'e', 'e', 'e', 'e',
                    'g',
                    'i', 'i', 'i', 'i', 'i',
                    'l', 'l', 'l',
                    'N', 'N', 'N',
                    'O', 'O', 'O', 'O', 'O', 'O', 'O',
                    'R', 'R',
                    'S', 'S', 'S',
                    'n', 'n', 'n',
                    'o', 'o', 'o', 'o', 'o', 'o',
                    'r', 'r',
                    's', 's', 's',
                    'T', 'T',
                    'U', 'U', 'U', 'U', 'U', 'U', 'U',
                    'Y', 'Y',
                    'Z', 'Z', 'Z',
                    't', 't',
                    'u', 'u', 'u', 'u', 'u', 'u', 'u',
                    'y', 'y',
                    'z', 'z', 'z',
                    'A', 'B', 'B', 'r', 'A', 'E', 'E', 'X', '3', 'N', 'N', 'K', 'N', 'M', 'H', 'O', 'N', 'P',
                    'a', 'b', 'b', 'r', 'a', 'e', 'e', 'x', '3', 'n', 'n', 'k', 'n', 'm', 'h', 'o', 'p',
                    'C', 'T', 'Y', 'O', 'X', 'U', 'u', 'W', 'W', 'b', 'b', 'b', 'E', 'O', 'R',
                    'c', 't', 'y', 'o', 'x', 'u', 'u', 'w', 'w', 'b', 'b', 'b', 'e', 'o', 'r'
                    ];
            
            // Remplace les espaces par des underscore _, supprime les séparateurs de dossiers et les points et préserve le maximum de caracatères utiles.
            var regex;
            $.each(cible,function(i,v)
            {
                    regex = new RegExp(v, "g");
                    dossier = dossier.replace(regex,rempl[i]);
            });
            
            
            // Remplace tous les caractères non autorisé par -
            dossier = dossier.replace(/[^a-z0-9_-]+/gi, '-');
            // Supprime les occurences successives de - 
            dossier = dossier.replace(/-{2,}/,'-',dossier);
            // Supprime le premier et le dernier - 
            dossier = dossier.replace(/^-+/,'');
            dossier = dossier.replace(/-+$/,'');
     
            return dossier;
    }
     
    })
    </script>
    </html>



    Fichier serveur "Php_Upload/UploadAjaxABCI_Upload_Redimensions_Album.php"
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    <?php
    session_start();
     
    header('Content-type: text/html; charset=UTF-8');// Inutile depuis php 5.6
     
     
    // Vous devez vérifier l'existence du dossier ou changer cette adresse 
    /*------------------------------------------------------*/
    $repertoire_destination = '../Album_Photo/';
    /*------------------------------------------------------*/
     
     
    // Charge la classe php d'upload et la classe de redimensionnement avec spl_autoload_register
    spl_autoload_register(function ($class) {require 'Classes/' . $class . '.php';});
     
    // On initialise ici la classe d'upload sans paramètre. La destination du fichier sera définie par le paramètre passé dans la fonction Tranfert()
    $up = new UploadAjaxABCIServeur();
     
    // Décommenter la ligne ci-dessous en phase de développement pour faire afficher les erreurs php dans le formulaire.
    // $up->setModeDebug ();
     
     
    // Voir le mode d'emploi pour des informations complémentaires sur la gestion des erreurs fatales.
    $tab_erreurs = [];
    $tab_erreurs['Allowed memory size'] = SetMessages::get('UpAbAllowedMemorySize');
    $tab_erreurs['Maximum execution time'] = SetMessages::get('UpAbMaximumExecutionTime');
    $up->cathErrorServeur($tab_erreurs);
     
    $uniqid_form = $up->getParam("uniqid_form");
     
    if(!(isset($uniqid_form,$_SESSION['UploadAjaxABCI'][$uniqid_form]['token']))) $up->exitStatusErreur(SetMessages::get('UpAbVerifToken')); 
     
    /* 
    J'utilise des variables de session sous la forme $_SESSION['UploadAjaxABCI'][$index1][$index2] pour préserver l'espace de nom. Et j'assigne ces variables par référence à d'autres variables pour simplifier l'écriture. Attention de ne pas utiliser "token" et "unsetSesInit" comme index2 car ils sont déjà utilisés.
    
    Le quatrième paramètre est utilisé pour supprimer ou non les variables de session avec la fonction unsetSesInit(), à la fin du traitement du formulaire dans la condition if(count($up->UpAbci_formEnd) > 0), ou lors de l'emploi de la fonction stopFormExit() en cas d'erreur de contrôle du formulaire.
    */
    function &sesInit($index1, $index2, $defaut, $unset=true)
    {
    	$_SESSION['UploadAjaxABCI'][$index1][$index2] = isset($_SESSION['UploadAjaxABCI'][$index1][$index2]) ? 	$_SESSION['UploadAjaxABCI'][$index1][$index2] : $defaut;
     
    	// Enregistre les index des variables de session à effacer en fin de traitement du formulaire
    	if($unset) {$_SESSION['UploadAjaxABCI'][$index1]['unsetSesInit'][] = $index2;}
     
    	return $_SESSION['UploadAjaxABCI'][$index1][$index2];
    }
     
     
     
    // Fonction pour supprimer les variables de session enregistrées dans $_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit'] 
    function unsetSesInit($uniqid_form)
    {
    	// N'efface que les variables dynamiques construites avec $uniqid_form
    	if(isset($_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit']))
    	{
    		foreach($_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit'] as $index2)
    		{
    			if(isset($_SESSION['UploadAjaxABCI'][$uniqid_form][$index2])) unset($_SESSION['UploadAjaxABCI'][$uniqid_form][$index2]);
    		}
    		unset($_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit']);
    	}
    }
     
     
     
    /*
    Création d'une fonction qui :
    - Stoppe le traitement de l'ensemble du formulaire a réception de la requête ajax, 
    - Ajoute un message dans le bloc html ayant la classe UpAbci_infosServer avec addInfosServer 
    et/ou 
    - Passe un objet dans mixte_serveur avec addMixteServer, récupérable dans la fonction événementielle config.func_FormEnd 
    - Efface les variables de session enregistrées dans $_SESSION['UploadAjaxABCI'][$uniqid_form]['unsetSesInit']
    - Et sort du script php en cours.
    */
    function stopFormExit ($up, $infos_server=null, $mixte_server=null)
    {
    	// Commande à javascript de stopper la soumission du formulaire à réception de la requête ajax.
    	$up->stopForm();
    	// addInfosServer envoie un message dans le bloc html ayant la classe UpAbci_infosServer
    	if(isset($infos_server)) $up->addInfosServer ($infos_server);
    	// addMixteServer passe un objet (texte, html ou tableau) qui pourra être récupéré en troisisème paramètre dans la fonction événementielle "config.func_FormEnd"
    	if(isset($mixte_server)) $up->addMixteServer ($mixte_server);
    	// Efface certaines variables de sessions (cf unsetSesInit)
    	unsetSesInit($up->getParam("uniqid_form"));
    	// Et sort du traitement php en envoyant les informations nécessaires vers javascript
    	$up->exitReponseAjax();
    }
     
     
     
     
    /*
    Les variables utilisant l'index dynamique $uniqid_form seront réinitialisées automatiquement par le visiteur à chaque rafraichissement de la page du formulaire puisque c'est l'identifiant unique généré par le formulaire au chargement de la page.
    */
     
    /*
    Les variables ci-dessous sont utilisées en fin de traitement du formulaire dans la condition if(count($up->UpAbci_formEnd) > 0)
    */
     
    // Initialisation d'une variable de session pour enregistrer les fichiers traités et transférés.
    $ses_files =& sesInit($uniqid_form, 'files', []);
     
    // Initialisation d'une variable de session pour enregistrer le dossier de destination. 
    $ses_dir =& sesInit($uniqid_form, 'dir', null);
     
    // Initialisation d'une variable de session pour enregistrer l'affichage du message de création d'un nouvel album et ne le faire afficher qu'une seule fois en cas de soumissions multiples du formulaire tant qu'on utilise le même album ($ses_new_dir_message sera effacée en fin de traitement du premier formulaire avec unsetSesInit()).
    $ses_new_dir_message =& sesInit($uniqid_form, 'new_dir_message', null);
     
    // Initialisation d'une variable de session pour mettre à jour le select dans le html.
    $ses_new_option_select =& sesInit($uniqid_form, 'new_option_select', null);
     
     
    // Initialisation d'une variable de session pour enregistrer la valeur d'un nouveau dossier avant nettoyage. "false" est passé en 4ème paramètre pour éviter la suppression de cette variable de session en fin de traitement du formulaire avec unsetSesInit(). Cela permettra au visiteur de compléter un nouvel album dernièrement créé tant qu'il n'a pas rafraichi la page du formulaire, sans rentrer dans le message d'erreur défini dans la condition if(!isset($ses_new_dir_post) utilisée plus bas.
    $ses_new_dir_post =& sesInit($uniqid_form, 'new_dir_post', null, false);
     
     
    /*
    Les variables ci-dessous sont utilisées pour loger les dossiers existants qui ont été complétés
    */
     
    /* 
    Log une seule fois par session utilisateur (tant que l'utilisateur utilise le même dossier)
    - Pour définir des variables de session valables durant toute la session de l'utilisateur, on peut utiliser l'index statique $up->getParam("id_form") qui retourne l'identifiant (id ou class) du formulaire. Cela permet éventuellement de traiter plusieurs formulaires différents avec le même script côté serveur sans craindre de conflit de variables, pour peu que les différents formulaires aient des identifiants différents.
    */
    // $ses_last_select est utilisée pour enregistrer le nom du dernier album sélectionné.
    $ses_last_select =& sesInit($up->getParam("id_form"), 'last_select', null, false);
     
    // $ses_dir_select_log est utilisée pour ne faire le log qu'une seule fois par session tant que le dossier sélectionné n'a pas changé.
    $ses_dir_select_log =& sesInit($up->getParam("id_form"), 'dir_select_log', null, false);
     
     
     
     
     
    // Création d'une fonction pour avoir des noms de dossiers valides sur tous les serveurs
    function cleanDossier($up, $name)
    {		
    	$cible = [
    	' ', '/', '.',
    	'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ă', 'Ą',
    	'Ç', 'Ć', 'Č', 'Œ',
    	'Ď', 'Đ',
    	'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ă', 'ą',
    	'ç', 'ć', 'č', 'œ',
    	'ď', 'đ',
    	'È', 'É', 'Ê', 'Ë', 'Ę', 'Ě',
    	'Ğ',
    	'Ì', 'Í', 'Î', 'Ï', 'İ',
    	'Ĺ', 'Ľ', 'Ł',
    	'è', 'é', 'ê', 'ë', 'ę', 'ě',
    	'ğ',
    	'ì', 'í', 'î', 'ï', 'ı',
    	'ĺ', 'ľ', 'ł',
    	'Ñ', 'Ń', 'Ň',
    	'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ő',
    	'Ŕ', 'Ř',
    	'Ś', 'Ş', 'Š',
    	'ñ', 'ń', 'ň',
    	'ò', 'ó', 'ô', 'ö', 'ø', 'ő',
    	'ŕ', 'ř',
    	'ś', 'ş', 'š',
    	'Ţ', 'Ť',
    	'Ù', 'Ú', 'Û', 'Ų', 'Ü', 'Ů', 'Ű',
    	'Ý', 'ß',
    	'Ź', 'Ż', 'Ž',
    	'ţ', 'ť',
    	'ù', 'ú', 'û', 'ų', 'ü', 'ů', 'ű',
    	'ý', 'ÿ',
    	'ź', 'ż', 'ž',
    	'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р',
    	'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'р',
    	'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
    	'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я'
    	];
     
    	$rempl = [
    	'_', '', '',
    	'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'A', 'A',
    	'C', 'C', 'C', 'CE',
    	'D', 'D',
    	'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'a', 'a',
    	'c', 'c', 'c', 'ce',
    	'd', 'd',
    	'E', 'E', 'E', 'E', 'E', 'E',
    	'G',
    	'I', 'I', 'I', 'I', 'I',
    	'L', 'L', 'L',
    	'e', 'e', 'e', 'e', 'e', 'e',
    	'g',
    	'i', 'i', 'i', 'i', 'i',
    	'l', 'l', 'l',
    	'N', 'N', 'N',
    	'O', 'O', 'O', 'O', 'O', 'O', 'O',
    	'R', 'R',
    	'S', 'S', 'S',
    	'n', 'n', 'n',
    	'o', 'o', 'o', 'o', 'o', 'o',
    	'r', 'r',
    	's', 's', 's',
    	'T', 'T',
    	'U', 'U', 'U', 'U', 'U', 'U', 'U',
    	'Y', 'Y',
    	'Z', 'Z', 'Z',
    	't', 't',
    	'u', 'u', 'u', 'u', 'u', 'u', 'u',
    	'y', 'y',
    	'z', 'z', 'z',
    	'A', 'B', 'B', 'r', 'A', 'E', 'E', 'X', '3', 'N', 'N', 'K', 'N', 'M', 'H', 'O', 'N', 'P',
    	'a', 'b', 'b', 'r', 'a', 'e', 'e', 'x', '3', 'n', 'n', 'k', 'n', 'm', 'h', 'o', 'p',
    	'C', 'T', 'Y', 'O', 'X', 'U', 'u', 'W', 'W', 'b', 'b', 'b', 'E', 'O', 'R',
    	'c', 't', 'y', 'o', 'x', 'u', 'u', 'w', 'w', 'b', 'b', 'b', 'e', 'o', 'r'
    	];
     
    	// Remplace les espaces par des underscore _, supprime les séparateurs de dossiers et les points et préserve le maximum de caracatères utiles.
    	$name = str_replace($cible, $rempl, $name);
    	// Remplace tous les caractères non autorisé par -
    	$name = preg_replace('#[^a-z0-9_-]+#i', '-', $name);
    	// Supprime les occurences successives de '-'
    	$name = preg_replace('#-{2,}#','-', $name);
    	// Supprime le premier et le dernier "-" 
    	$name = trim($name,"-");
     
    	if($name == '')
    	{
    		$message = '<div style="border:3px solid red;border-radius:5px;color:red;padding:0.5em;margin-top:1em">Nom d\'album "<strong>'.htmlspecialchars($name).'</strong>" non valide. Traitement du formulaire annulé.</div>';
    		stopFormExit ($up, $message, 'annule');
    	}
    	else
    	return $name;
    }
     
     
    /* 
    Ne pas mettre ces lignes à l'intérieur de la condition "if $up->getFragment" car ces variables sont utilisées en fin de page pour exploiter la requête additionnelle de fin de traitement du formulaire qui ne contient pas de fragment de fichier.
    */
    $select_dir_clean = isset($_POST['dossier_name']) && trim($_POST['dossier_name']) != '' ? cleanDossier($up, trim($_POST['dossier_name'])) : null;
     
    $new_dir_post = isset($_POST['new_dossier_name']) && trim($_POST['new_dossier_name']) != '' ? trim($_POST['new_dossier_name']) : null;
    $new_dir_clean = isset($new_dir_post) ? cleanDossier($up, $new_dir_post) : null;
     
     
    // S'assure qu'un fichier ou un fragment de fichier est en téléchargement
    if($up->getFragment())
    {
    	$filesExtensions = ['jpg','jpeg','png','gif'];
     
    	$nom_fichier_nettoye = $up->getCleanFileName();
     
    	$verif_extension = $up->verifExtensions($nom_fichier_nettoye,$filesExtensions);
    	if($verif_extension == false) 
    	{
    		$up->exitStatusErreur(SetMessages::get('UpAbExtensionFichier'));
    	}	
     
    	// Par sécurité on refait le contrôle déjà effectué en javascript
    	if($select_dir_clean == '' && $new_dir_clean == '')
    	{
    		$message = '<div style="border:3px solid red;border-radius:5px;color:red;padding:0.5em;margin-top:1em">Vous n\'avez choisi aucune option pour l\'album. Merci d\'en choisir une. Traitement du formulaire annulé.</div>';
    		stopFormExit ($up, $message, 'annule');
    	}
     
     
    	// Upload dans le dossier temporaire
    	$up->Upload();
     
    	// Retourne l'adresse du fichier temporaire quand il est complet, sinon false
    	$fichier_complet = $up->getTempAdressFileComplete();
    	if($fichier_complet != false)
    	{
    		// Si le champ nouvel album est renseigné avec un nom valide		
    		if($new_dir_clean != '') 
    		{
    			// Si le dossier n'existe pas
    			if(!is_dir($repertoire_destination.$new_dir_clean.'/mini')) 
    			{
    				// On tente de le créer
    				if(mkdir($repertoire_destination.$new_dir_clean.'/mini', 0777, true)) 
    				{
    					// Pour enregistrer le nouveau dossier et gérer les erreurs.
    					$ses_new_dir_post = $new_dir_post;
     
    					// Variable utilisée pour ne faire afficher le message de création d'album qu'une fois (tant que le visiteur n'a pas rafraichi sa page).
    					$ses_new_dir_message = $new_dir_clean;				
     
    					// On enregistre le nouveau dossier dans un tableau qui sera passé vers javascript avec addmixteServer et récupérable dans le troisième paramètre de la fonction événementielle "config.func_FormEnd" 
    					$ses_new_option_select = [$new_dir_clean => str_replace('_',' ',$new_dir_clean)];
     
     
    					// Log un nouveau dossier a été créé
    					// ...
     
     
    					// Les quatre lignes ci-dessous créent une page d'index ce qui interdit de lister directement le répertoire, vous pouvez les supprimer si besoin
    					$fp = fopen($repertoire_destination.$new_dir_clean.'/index.php', 'w');
    					$contenuindexphp = '[...]';
    					fwrite($fp, $contenuindexphp);
    					fclose($fp);
    				}
    				else // Erreur dans la création du dosssier
    				{
    					// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    					$message = '<div style="border:3px solid red;border-radius:5px;color:red;padding:0.5em;margin-top:1em">Erreur dans la création du dossier "'.htmlspecialchars(str_replace('_',' ',$new_dir_clean)).'". Traitement du formulaire annulé.</div>';
    					stopFormExit ($up, $message, 'annule');
    				}
    			}
    			else if(!isset($ses_new_dir_post) || $ses_new_dir_post != $new_dir_post)
    			{
    				/* 
    				On arrive dans cette condition si 
    				1/ le visiteur a utilisé le champ "nouvel album" et a saisi le nom d'un album déjà existant (le dossier existe déjà et $ses_new_dir_post n'a pas été défini) 
    				ou
    				2/ Après avoir créé un nouvel album, il tente d'en créer un second (différent) en rentrant le nom d'un dossier déjà existant et dans ce cas $ses_new_dir_post != $new_dir_post.
    
    				
    				On annule le formulaire et on envoie un message d'erreur car l'action ne correspond pas à la création d'un nouvel album.
    				
    				C'est un contrôle de sécurité côté serveur qui ne devrait jamais apparaître dans un fonctionnement normal puisque le même contrôle est fait côté client, aussi je détaille moins la réponse que côté client.
    				*/
    				$message =  
    				'<div style="border:3px solid red;border-radius:5px;color:red;padding:0.5em;margin-top:1em">Le nouvel album "'.htmlspecialchars(str_replace('_',' ',$new_dir_clean)).'" existe déjà. Utilisez le sélecteur d\'album pour compléter un album existant. Traitement du formulaire annulé.</div>';
     
    				stopFormExit ($up, $message, 'annule');
    			}
     
    			// Dossier utilisé pour l'upload
    			$ses_dir = $new_dir_clean;
    		}
    		else if ($select_dir_clean != '') // Sélection d'album
    		{
    			if(is_dir($repertoire_destination.$select_dir_clean.'/mini')) // Si le dossier existe
    			{
    				// Condition pour éviter un log de dossier pour chaque fichier téléchargé. Si le dossier sélectionné est différent du dernier sélectionné déjà enregistré
    				if ($select_dir_clean != $ses_last_select)
    				{
    					// On enregistre le dossier dans la variable de session
    					$ses_last_select = $select_dir_clean;
     
    					// On pourrait faire le log ici mais aucun fichier n'a encore été transféré et donc en cas d'erreur de redimensionnement d'image par exemple, le fichier sera rejeté et le dossier ne sera pas complété. Pour enregistrer un log qui témoigne qu'un dossier a réellement été mis à jour, il faut reporter ce log dans la condition if (transfert) et je délègue cette tâche à la variable de session $ses_dir_select_log;
    					$ses_dir_select_log = $select_dir_clean;
    				}
     
    				// Dossier utilisé pour l'upload
    				$ses_dir = $select_dir_clean;
    			}
    			else // Erreur 
    			{
    				// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    				$message = '<div style="border:3px solid red;border-radius:5px;color:red;padding:0.5em;margin-top:1em">Le dossier sélectionné "'.$repertoire_destination.$select_dir_clean.'/mini'.'" n\'est pas valide. Traitement du formulaire annulé.</div>';
    				stopFormExit ($up, $message, 'annule');
    			}
    		}
     
    		$dossier_destination = $repertoire_destination.$ses_dir.'/';
    		$dossier_mini = $dossier_destination.'mini/';
     
    		/* 
    		La classe CorrectionExifJpg corrige l'orientation des images jpg en fonction de ses informations EXIF. 
    		Il faut l'utiliser avant les traitements sur les images car les largeurs et hauteurs pourront être inversées. 
    		Cette classe peut émettre des exceptions, à utiliser dans un bloc try/catch. 
    		*/
    		try 
    		{ 	
    			CorrectionExifJpg::filePath($fichier_complet);
    		}
    		catch (Exception $e) 
    		{
    			// Stoppe le fichier en cours et renvoie le message d'erreur dans le status du fichier
    			$up->exitStatusErreur($e->getMessage());
    		}
     
     
    		/*
    		Si plusieurs redimensionnements on utilise les troisième et quatrième paramètre de la classe "RedimImage()" qui vont copier le fichier redimensionné dans le répertoire de destination et laisser intact le fichier original.
    		Ci-dessous je crée une fonction qui réalise la redimension et impose le chmod au fichier de destination
    		
    		La fonction RedimImage peut renvoyer des exceptions, il faut donc utiliser un bloc try/catch
    		*/
    		function Redim($L, $H, $dossier_dest=null, $nom_fichier=null, $dirname, $basename, $extension_fichier, $up)
    		{
    			try
    			{
    				RedimImage::Param($L, $H, $dossier_dest, $nom_fichier, $dirname, $basename, $extension_fichier);
    			}
    			catch (Exception $e)
    			{
    				$up->exitStatusErreur($e->getMessage());
    			}
     
    			// On met le chmod si besoin (mini 0604 pour une lecture depuis une url externe) au cas où le serveur mette un 0600
    			$destination_fichier = $dossier_dest.$nom_fichier;
    			if(trim($destination_fichier) != '' && !@chmod($destination_fichier,0604))
    			{
    				$up->exitStatusErreur(SetMessages::get('UpAbConfigChmod'));
    			}
    		}
     
    		// Informations sur le fichier
    		$pathinfo = pathinfo($nom_fichier_nettoye);
    		$extension_fichier = strtolower($pathinfo['extension']);
    		$non_fichier = $pathinfo['filename'];
     
    		// On utilise l'adresse du fichier temporaire (fichier de travail) pour le passer en paramètre à la fonction de redimensionnement
    		$basename = basename($fichier_complet);
    		$dirname = dirname($fichier_complet).'/';
     
    		/* 
    		On fait le plus grand redimensionnement en premier dans le répertoire temporaire en modifiant la source. Les redimensionnements suivants utiliseront cette image redimensionnée et donc moins de ressources serveur par rapport à l'image originale. Il faut bien entendu que les redimensionnements suivants soient de dimensions inférieures.
    		*/
    		Redim(1500, 1500, '', '', $dirname, $basename, $extension_fichier, $up);
    		// On construit l'adresse du premier fichier redimensionné pour le passer en paramètre à la fonction "Transfert()"
    		$nom_fichier_max = $non_fichier.'.'.$extension_fichier;
    		$destination_fichier = $dossier_destination.$nom_fichier_max;
     
    		// Redimensionnements suivants en utilisant le premier comme source et en copiant le résultat dans le répertoire de destination (ne modifie pas la source)
    		$nom_fichier_min = $non_fichier.'.'.$extension_fichier;
    		Redim(150, 150, $dossier_mini, $nom_fichier_min, $dirname, $basename, $extension_fichier, $up);
     
    		// La fonction "Transfert()" transfère le fichier du répertoire temporaire vers sa destination finale. Retourne true si ok.
    		$transfert = $up->Transfert($destination_fichier);
     
    		// On défini le chmod (si besoin)
    		if($transfert && !@chmod($destination_fichier,0604))
    		{
    			$up->exitStatusErreur(SetMessages::get('UpAbConfigChmod'));
    		}
     
    		// Si on arrive ici c'est que tout c'est bien passé, sinon les $up->exitStatusErreur() utilisés en cas d'erreur arrêtent le script et envoient le message correspondant. On pourrait donc enregistrer ici le(s) nom(s) du fichier en bdd. 
     
    		if($transfert)
    		{
    			// Si la variable $ses_dir_select_log est définie on peut faire le log témoignant qu'un dossier sélectionné a été complété.
    			if(isset($ses_dir_select_log) && $ses_dir_select_log == $select_dir_clean)
    			{
    				// On efface ses_dossier_selection_log pour ne faire le log qu'une fois. unset() ne fonctionne pas pour les variables passées par référence, il faut utiliser la constante null)
    				$ses_dir_select_log = null; 
     
    				// Log en utilisant $select_dir_clean
    				// ...
    			}
     
     
    			/* 
    			J'enregistre les fichiers uploadés dans une variable de session qui seront exploitées à la fin du traitement du formulaire. 
    			Cette méthode est à réserver pour des informations visiteur plutôt que pour des traitements dont la défaillance pourrait perturber l'intégrité des données du site, car si une panne internet survient avant la fin du traitement de tout le formulaire, on ne pourra pas exploiter ces variables dans la condition if(count($up->UpAbci_formEnd) > 0) puisque le tableau $up->UpAbci_formEnd ne sera jamais reçu.
    			
    			Il est plus sécurisé de loguer les fichiers uploadés ici (dans la condition if($transfert)) les uns après les autres pour être certain de n'en manquer aucun. 
    			
    			$up->getParam("name") retourne le nom originel du fichier. J'utilise cette construction pour pouvoir récupérer facilement le nom du fichier nettoyé avec le tableau récapitulatif $up->UpAbci_formEnd retourné en fin de traitment du formulaire.
    			*/
    			$ses_files[$up->getParam("name")] = $nom_fichier_nettoye;
    		}		
    	}
    }
     
     
     
     
    /* 
    Si ET SEULEMENT SI on défini l'option "config.queryFormEnd = true" dans la configuration javascript du formulaire, une requête additionnelle est envoyée vers le serveur à la fin du traitement du formulaire. Elle contient les variables $_POST communes à tout le formulaire (non spécifiques à chaque fichier), et un tableau récapitulatif de l'upload pour chaque fichier (y compris les éventuels inputs spécifiques à chaque fichier) récupérable avec la propriété "UpAbci_formEnd" de la classe php. 
    
    Si ce n'est pas la fin du traitement du formulaire ou si l'option javascript n'est pas configurée, $up->UpAbci_formEnd renvoie un tableau vide. Cf mode d'emploi "Configuration serveur -> Récupération des paramètres Ajax prédéfinis".
    */
    if(count($up->UpAbci_formEnd) > 0)
    {
    	// Ici on peut exploiter $ses_files et $ses_dir en pensant à les effacer à la fin du traitement pour éviter un conflit en cas d'envois successifs du formulaire.
     
    	// On peut vérifier que les fichiers ont été correctement transférés en testant l'index "result" qui doit retourner "ok_done".
    	$result = 0;
    	foreach($up->UpAbci_formEnd as $file)
    	{
    		if($file['result'] == "ok_done")
    		{
    			$result++;
     
    			/* 
    			pour info :
    			- le nom originel du fichier est $file['name']
    			- le nom du fichier nettoyé est donc $ses_files[$file['name']] 
    			Attention : si vous souhaitez récupérer $ses_files[$file['name']] en dehors de la condition if($file['result'] == "ok_done"), il faudra le tester avec "isset" car cet item n'est défini que pour les fichiers transférés (cf la construction de la variable de session $ses_files plus haut à l'intérieur de la condition if ($transfert)).
    			*/
    		}
    	}
     
     
    	$nom_album = str_replace('_', ' ',$ses_dir);
    	$message_fin = $result == count($up->UpAbci_formEnd) ? 'Toutes les photos ont bien été ajoutées dans l\'album "'.htmlspecialchars($nom_album).'"' : 'Certaines photos n\'ont pas été ajoutées dans l\'album "'.htmlspecialchars($nom_album).'". Voir le détail dans la liste ci-dessous.';
     
    	// Le message de création d'un nouveau dossier sera envoyé une seule fois tant que l'utilisateur ne rafrachi pas sa page et s'il utilise le même dossier, en testant $ses_new_dir_message == $new_dir_clean car $ses_new_dir_message est effacée plus bas avec unsetSesInit() et n'est définie que lors de la création d'un nouveau dossier.
     
    	// Je construis un message différent si un nouvel album a été créé ou non.
    	// Pensez à utiliser htmlspecialchars pour faire afficher des variables utilisateur sinon le message final pourra être tronqué
    	$message = isset($new_dir_clean,$ses_new_dir_message) && $ses_new_dir_message == $new_dir_clean ? 
    	'Adresse du nouvel album : <a target="_blank" href="Album_Photo/'.htmlspecialchars($ses_dir).'/">Album_Photo/'.htmlspecialchars($ses_dir).'/</a><br>'.$message_fin : $message_fin;
     
    	$message = '<div style="border:3px solid #F90;border-radius:5px;color:black;padding:0.5em;margin-top:1em">'.$message.'</div>';
     
     
    	// Envoi du message dans l'élément html ayant la classe UpAbci_infosServer
    	$up->addInfosServer($message);
     
    	// Envoi du tableau pour la mise à jour du select
    	if (isset($ses_new_option_select)){$up->addMixteServer($ses_new_option_select);}
     
    	// Ne pas oublier de supprimer ces variables de session en fin de traitement du formulaire
    	unsetSesInit($uniqid_form);
     
     
    	// Pour voir facilement le contenu de UpAbci_formEnd en phase de développement (sera affiché dans l'élément html ayant la classe UpAbci_infosServer)
    	/*
    	ob_start();
    	echo '<pre>'.var_dump($up->UpAbci_formEnd).'</pre>';
    	$dump = ob_get_contents();
    	ob_end_clean();
    	$up->addInfosServer($dump);
    	*/
     
    }
    $up->exitReponseAjax();
    ?>

  11. #191
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 957
    Points : 44 119
    Points
    44 119
    Par défaut
    Bonjour,
    Le contenu du tableau javascript nommé "cible" est corrompu par les balises code de ce site. Je le redonne donc ici
    essaie avec le balisage [PRE]ton code ...[/PRE] voir si le résultat te convient.

  12. #192
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    @NoSmoking
    Merci, ça casse la coloration syntaxique mais les boutons "sélectionner tout" restent fonctionnels et finalement c'est mieux que de devoir recopier une partie du code à l'extérieur des balises code.

    EDIT : je viens de voir aussi que le lien "Visualiser dans une fenêtre à part" ne respecte pas tous les caractères quand j'utilise cette méthode aussi j'ai mis un message en ce sens. Dis-moi si on peut faire mieux, cela me semble être le meilleur compromis.

  13. #193
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 957
    Points : 44 119
    Points
    44 119
    Par défaut
    EDIT : ... Dis-moi si on peut faire mieux, cela me semble être le meilleur compromis.
    après quelques tests il semblerait que ce soit l'encodage (charset=iso-8859-1) des pages qui me semble mettre le bazar (sûrement pas que), désolé.

  14. #194
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2017
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2017
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Erreur de connexion
    J'essaie de faire fonctionner le package et j'ai systématiquement l'erreur
    {"upabci_erreur":"Connexion non valide ou perdue. Rafra\u00eechissez la page et recharger \u00e9ventuellement votre fichier, si celui-ci dispose d'une sauvegarde automatique elle sera utilis\u00e9e."}

    Le problème se produit sur mon serveur Wamp en local et aussi sur FREE.

    Je ne trouve pas d'informations sur l'origine du problème.
    Est-ce que quelqu'un a une idée.

  15. #195
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Bonjour,

    Quand cela ne fonctionne pas du tout, ce qui est assez rare puisque tu es apparemment la première personne à qui cela arrive (premier message dans ce sens), il faut lire le chapitre debug du mode d'emploi. Il y a quelques temps aussi, il fallait créer un dossier nommé session pour actionner les sessions chez free.

    Pour wamp je comprend pas trop, tu utilises quelle version de wamp ?

  16. #196
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut Module Upload Ajax PHP mise à jpur
    La version 7.2 est disponible.

    A/ Corrections
    Classe javascript
    1/ Bug version 7.0 uniquement : Il y avait une incompatibilité entre les options de configurations javascript config.submitWithoutFile et config.inputFormAttrOnSubmit. La soumission du formulaire sans fichiers joints ne permettait pas la réinitialisation des inputs si les deux options étaient utilisées conjointement.
    2/ Bug versions 7.0 et 7.1 : Le bouton "arrêter tout" restait fonctionnel après la fin du traitement du formulaire. Cela provoquait un affichage erroné (mais sans conséquence réelle) si l'on cliquait sur ce bouton après la fin du traitement même si cela n'avait aucun effet sur les fichiers téléchargés.

    Classe php
    1/ Bug version 7.0 uniquement : Corrections de la classe Php_Upload/Classes/CorrectionExifJpg. La fonction exif_read_data pouvait pour certaines (rares) images, renvoyer un warning bien que cela ne soit pas spécifié dans la doc php.
    2/ Bug TOUTES versions : L'index iteration_form qui retourne le nombre d'itération de la requête ajax pour le traitement du formulaire, disponible dans les tableaux $UpAbci_form et $UpAbci_formEnd (cf mode d'emploi : Configuration serveur->Récupération des paramètres Ajax prédéfinis) ne retournait pas la bonne valeur dans tous les cas. C'était un bug toutes versions mais négligeable dans le sens où cette valeur est rarement utile et jamais utilisée dans les exemples fournis.

    B/ Modification du comportement par défaut de la classe javascript
    Précédemment et toutes versions confondues, le bloc d'information spécifique aux fichiers, renseigné en troisième paramètre dans l'initialisation de la classe javascript, était réinitialisé automatiquement en cas de soumissions multiples du formulaire. C'était un comportement logique dans la plupart des cas, mais qui pouvait s'avérer gênant dans certaines conditions particulières, par exemple si l'on veut garder l'affichage des fichiers déjà uploadés dans le cas de soumissions multiples. Ce comportement automatique a été supprimé pour préserver un maximum de possibilités de programmation et d'affichage, et n'a pas été remplacé par une option javascript correspondante car l'on peut faire l'équivalent de ce comportement en appliquant conjointement les styles événementiels data-upabcicss-submit="display:none" et data-upabcicss-submit-file="display:block" sur le bloc d'information des fichiers.

    C/ Ajout d'un fichier d'exemple
    Le fichier d'exemple pour la création/modification d'albums photo (cité dans mes derniers messages) a été légèrement amélioré et intégré dans le dossier de test prêt à l'emploi.

    ...et quelques corrections mineures ont été faites dans le mode d'emploi.



    Voilà


    (note : la version 7.1 n'a été disponible que quelques jours. La version 7.2 corrige le paramétrage de certains styles événementiels dans quelques fichiers d'exemples qui avaient été oubliés dans la version 7.1 pour tenir compte de la modification de comportement indiqué ci-dessus, ainsi que le point n°2 des corrections javascript)

  17. #197
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Bonjour,

    Mise à jour du mode d'emploi dans la nouvelle version v7.2cc

    Aucune correction/modification de code dans les classes Javascript et Php par rapport à la version 7.2

    Quelques micro optimisations sans importance et la méthode interne Javascript "FormateBits" à été renommée "FormateOctets" pour éviter toute confusion. Cela ne change rien au fonctionnement interne ni au paramétrage de la classe.

    Petites modifications dans le contenu du mode d'emploi, et plus particulièrement dans le fonctionnement du menu qui permet maintenant de visualiser le positionnement de l'information dans le menu depuis un lien externe ou interne si ce lien correspond à un chapitre du menu.

  18. #198
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Citation Envoyé par userweb Voir le message
    Faisant suite à ton retour courriel donc j'ai essayé
    d'utiliser le folder complet ajax/php via Wamp server
    toutefois il n'y a pas la possibilité de visualiser les exemples .php
    car un retour d'erreur d'alinéa de codage s'inscrit donc je ne peux
    que visualiser les explications texte .
    C'est pour cela que je voulais t'envoyer ma mise en page afin
    que tu puisses peut-être trouver la possibilité d'utiliser
    ce système de type Drag and Drop via cette pagination .
    Merci pour ta compréhension .
    En te souhaitant une excellente semaine .
    La première chose à faire, c'est de poser le dossier (dézippé) sur ton serveur et de tester les exemples fournis. Tu peux utiliser le mode d'emploi (le fichier index.html inclus dans le dossier) pour avoir la liste et les liens correspondants.

    Pour débuguer il faut absolument donner le contexte précis :
    - Quel fichier utilises-tu ?
    - Quel action fais-tu avec ce fichier qui entraine ce bug ?
    - Et surtout RECOPIE LE MESSAGE D'ERREUR qui s'inscrit et montre-le nous, c'est avec ce message qu'on pourra te donner la solution.

    Donnes également la version de php que tu utilises, tu peux la connaitre en cliquant sur l'icone de wampserveur dans la barre des taches (après qu'il soit lancé).

  19. #199
    Invité
    Invité(e)
    Par défaut
    Merci pour ton aide par rapport à ma demande .
    Je vais vérifier tout cela cette semaine afin d'obtenir
    la visibilité via WampServer de ces paginations .
    Je te recontacte par la suite si bien entendu cela ne
    te dérange pas.
    J'ai fais plusieurs essai à partir du script de base .php
    mais aucun résultat correct afin de disposer d'un "système"
    d'upload de type Drag and Drop .
    En te souhaitant une excellente semaine .

  20. #200
    Invité
    Invité(e)
    Par défaut
    ABCIWEB,

    Donc je reviens sur ce post ; il y a une erreur au niveau de l'alinéa suivant : $val = str_replace([',',' '],['.',''],$val);
    Le serveur Wamp me retourne une erreur à partir du fichier .php dénommé UploadABCIServices.php
    Dois-je ajouter un quotat spécifique au sein de cette variable afin de visualiser les modèles d'exemples car
    il n'y a que le fichier index.html explicatif qui est visible à l'écran et non les fichiers de type .php .
    En te souhaitant une excellente journée .

+ Répondre à la discussion
Cette discussion est résolue.
Page 10 sur 15 PremièrePremière ... 67891011121314 ... DernièreDernière

Discussions similaires

  1. Upload de fichiers par fragments (chunk) - Erreur d'ouverture du fichier temporaire
    Par Kakolio dans le forum Bibliothèques & Frameworks
    Réponses: 5
    Dernier message: 10/07/2015, 18h27
  2. [SP-2007] Upload de gros fichiers par programme
    Par bigboomshakala dans le forum SharePoint
    Réponses: 10
    Dernier message: 31/03/2010, 09h55
  3. [Upload] Upload de GROS fichiers en php
    Par osscour dans le forum Langage
    Réponses: 21
    Dernier message: 26/05/2006, 14h13
  4. [Upload] Problème upload de gros fichiers avec Firefox
    Par the rootsm@n dans le forum Langage
    Réponses: 12
    Dernier message: 19/02/2006, 20h43
  5. [Upload] Upload de gros fichiers
    Par Rémiz dans le forum Langage
    Réponses: 8
    Dernier message: 07/01/2006, 11h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo