CVT Upload

CVT Upload fournit un interface générique de programmation (API), qui permet de gérer l’envoi d’un ou plusieurs fichiers par formulaire CVT. En cas d’erreur lors de la soumission du formulaire, les fichiers envoyés sont conservés temporairement dans SPIP afin que l’utilisateurtrice n’ait pas à les recharger.

Prérequis

Maitriser l’usage et la création des formulaires CVT de SPIP.

Installation

Il s’installe comme tous les plugins.

Il nécessite le plugin Médias (livré par défaut avec SPIP).

Il est recommandé d’utiliser les plugins suivants :

  • Saisies : permet de simplifier la déclaration HTML d’upload de fichiers ;
  • Vérifier : propose des fonctions prêtes à l’emploi pour vérifier que les fichiers uploadés sont conformes à la demande (ex. : j’en veux un seul à la fois, uniquement format PDF, etc.).

Comment fonctionne CVT Upload

Pour rappel, un formulaire CVT distingue :
-  la vue du formulaire dans le fichier .html
-  la déclaration des valeurs par défaut des champs du formulaire : fonction _charger dans le fichier .php
-  la vérification des valeurs : fonction _verifier dans le fichier .php
-  le traitement du formulaire : fonction _traiter dans le fichier .php.

Pour faire fonctionner CVT Upload il faut ajouter, toujours dans le fichier .php, la fonction _fichiers. On déclarera dans cette fonction les name des fichiers à uploader.

CVT Upload par l’exemple

L’objectif ici est de :

  1. détailler le fonctionnement du formulaire #FORMULAIRE_TEST_UPLOAD fourni en démo dans le plugin ;
  2. fournir un exemple de traitement des fichiers uploadés.

Vous trouverez les fichiers :

  • test_upload.html, qui correspond à l’affichage du formulaire côté utilisateurtrices ;
  • test_upload.php, qui correspond à la déclaration des champs d’upload, à leur vérification, à leur upload.

…dans le répertoire /formulaires du plugin.

Dans le fichier HTML : test_upload.html

  1. dans la balise form, ajout de l’attribut enctype="multipart/form-data"
    <form method="post" action="#ENV{action}" enctype="multipart/form-data">


    …prérequis à la déclaration de champ de type <input type="file">. Ce n’est pas particulièrement du SPIP, mais du HTML de base.

  2. les appels aux uploads fournit avec la syntaxe de base.
    À noter que les fichiers ../demo/test_upload_saisie.html et test_upload_saisie.php fournissent une syntaxe plus simple s’appuyant sur le plugin SAISIES.

Dans le fichier PHP : test_upload.php

Trois points importants :

  1. Inclusion l’API CVT Upload, c’est à dire toutes les fonctions commençant par cvtupload_…(…) et qui pourraient servir ici.
    include_spip('inc/cvtupload');
  2. Création de la fonction formulaires_test_upload_fichiers() dans laquelle on doit retrouver le ou les name des inputs de type file déclaré(s) dans le fichier .html. C’est grâce à cette fonction que les mécanismes de CVT Upload s’activent.
    function formulaires_test_upload_fichiers() {
    	return array('seul', 'plusieurs', 'image', 'plusieurs_images','pdf');
    }
  3. Dans la fonction _traiter, on récupère le tableau des fichiers uploadés à traiter [1]. Pour ce faire, il suffit d’utiliser _request('_fichiers') :
    function formulaires_test_upload_traiter() {
    	…
    	$fichiers = _request('_fichiers'); // hop, fichiers uploadés, récupérés ici pour traitement.
    	…
    }

C’est maintenant à vous d’appliquer le traitement que vous voulez :

  • enregistrer les fichiers dans la médiathèque de votre site ;
  • envoyer un PDF par mail ;
  • etc.

Exemple de traitement : associer les uploads à un objet éditorial

Plus précisément associer les documents à l’article 1 du site.

function formulaires_patates_traiter(){
  // récupérer le tableau des données correspondants aux fichiers uploadés ou non
  $fichiers = _request('_fichiers');
  
  if (is_array($fichiers) AND count($fichiers)) {
    // charger la fonction de chargement de document du plugin Medias
    $ajouter_documents = charger_fonction('ajouter_documents', 'action');

    // associer les documents uploadé à l'article 1 du site
    foreach ($fichiers as $key => $value) {
      $nouveaux_docs  = $ajouter_documents('new', $fichiers[$key], 'article', '1', 'auto');
    }
  }
  return $retours;
}

Notes : le dernier argument de la fonction $ajouter_documents a pour valeur ’auto’. Ainsi, c’est SPIP qui détermine automatiquement quel mode il doit donner pour chaque document.
Voir à ce propos le détail de la fonction ’ajouter_documents’

Notes

[1CVT Upload propose une structuration différente de $_FILES, plus simple de manipulation. Il est toutefois possible de continuer à utiliser $_FILES si souhaité.

Discussion

8 discussions

  • Bonjour,
    Besoin d’aide. J’utilise cvt_upload 2.1.1 avec formidable 5.3.0 sur spip 4.1.9 pour recevoir les demandes d’ adhésion dans notre ong mais je reçois cet erreur :

    Erreur d’exécution plugins/auto/cvtupload/v2.1.1/formulaires/inc-cvtupload-fichier.html | File […]/plugins/auto/cvtupload/v2.1.1/formulaires/inc-cvtupload-fichier_fonctions.php Line 37 : finfo_file() : Argument #1 ($finfo) cannot be empty

    Et coté public : Le fichier « Nom_du_fichier.jpg » n’a pas pu être stocké correctement par le système. Contactez le webmestre.
    Besoin d’aide svp

    Répondre à ce message

  • Répondre à ce message

  • 2

    Bonjour,
    Je reposte ici ce que j’ai déjà mis sous Formidable : une erreur lors de l’envoi de fichier joint dans mes formulaires de contact.

    Fatal error : Uncaught TypeError : array_merge() : Argument #1 must be of type array, string given in /racine_de_mon_site/plugins/auto/saisies/v4.3.3/inc/saisies_verifier.php:104 Stack trace : #0 /racine_de_mon_site/plugins/auto/saisies/v4.3.3/inc/saisies_verifier.php(104) : array_merge(’’, Array) #1 /racine_de_mon_site/plugins/auto/saisies/v4.3.3/saisies_pipelines.php(267) : saisies_verifier(Array) #2 /racine_de_mon_site/ecrire/inc/utils.php(236) : saisies_formulaire_verifier(Array) #3 /racine_de_mon_site/tmp/cache/charger_pipelines.php(581) : minipipe(’saisies_formula...’, Array) #4 /racine_de_mon_site/ecrire/inc/utils.php(303) : execute_pipeline_formulaire_verifier(Array) #5 /racine_de_mon_site/ecrire/public/aiguiller.php(255) : pipeline(’formulaire_veri...’, Array) #6 /racine_de_mon_site/ecrire/public.php(105) : traiter_formulaires_dynamiques() #7 /racine_de_mon_site/spip.php(20) : include(’/home/offmays/w...’) #8 main thrown in /racine_de_mon_site/plugins/auto/saisies/v4.3.3/inc/saisies_verifier.php on line 104

    Une idée de ce qui peut causer cela ?

    Merci d’avance.

    • L’erreur que tu colles indiques explicitement du code dans le plugin « Saisies », donc c’est ni dans Formidable ni dans CVT Upload qu’il faudrait la poster… (et pas besoin de la poster 3 fois à 3 endroits différents).

    • Désolé pour les posts multiples… J’avais d’abord posté sous « formidable », puis quelqu’un sur IRC m’a suggéré de le poster plutôt ici.

      Dois-je maintenant le remettre dans les coms de « saisies » ?

    Répondre à ce message

  • 9

    Bonjour,
    si il y a un document chargé, et pour afficher une case à cocher avant l’envoi, comment cibler avec un afficher_si ?
    Ou sinon est-ce qu’il est possible de surcharger le verifier de cvt_upload ?
    Merci bien
    touti

    • 1) il faut que je code un truc, je te fais cela asap
      2) il n’y pas de vérifier avec cvtupload, il y a des vérifie pour les fichiers (avec ou sans cvtupload), dans l’API verifier, que tu peux surcharger comme n’importe quel fichier (mais peut être vaudrait-il mieux voir si on ne pas l’étendre plutot)

    • La réponse est dans le plugin saisies/inc/saisies ligne 203 avec _request('cvtupload_fichiers_precedents') et $_FILES

      Dans le vérifier du CVT

      $televerse = _request('cvtupload_fichiers_precedents');
      
      if ((is_array($_FILES) AND count($_FILES) > 0) OR (is_array($televerse) AND count($televerse) > 0 )) {
      	$certifie_fichiers = _request('certifie_fichiers'); // case à cocher 
      	if($certifie_fichiers != 'on'){
      		$erreurs['certifie_fichiers'] = "Merci de certifier les droits de publication des images";
      	}
      }
    • J’ai un doute sur ce que tu veux tester. Est-ce l’envoi des fichiers par un formulaire, ou bien le fait que des fichiers soit présents d’un précedent envoi ? Je pense que tu devrais tester plutot directement sur _request(’fichiers’) (ou ’fichiers’ est le nom de ton champ).

    • Merci, j’ai donc bidouillé un truc @maieul et modifié mon post :)
      et bien évidemment testé _request(’fichiers’) ou autre qui ne marche pas

    • hum, je suis perdu. tu est tjr au point mort ?

    • Le code que je donne plus haut fonctionne comme attendu, il vérifie si il existe _FILES ou si il y a déjà un fichier chargé et envoi un message d’erreur pour la case qui doit être cocher.

      Par contre, pas réussi à faire disparaitre/apparaitre cette case avec un afficher_si

      Voila voila
      merci :)

    • La version 3.30.0 du saisies ajouter deux élèments à afficher_si :
      -  syntaxe @champ@:TOTAL > 2 pour vérifier qu’un champ de type checkbox a bien plus de deux case cochées
      -  syntaxe @champ@:TOTAL > 2 pour vérifier qu’un champ de type fichiers a bien plus de deux fichiers envoyés (dans ton cas : remplace le 2 par 0).

    • Bon, Il y avait bien un bug sur les afficher_si côté JS pour les fichiers. C’est corrigé normalement avec la version 3.,50.0 du plugins saisies + 1.22.0 de cvt-upload.

    • note : avec cela tu pourrais du coup simplement utilise l’API de vérification des saisies (saisies_verifier), et rendre ta case à cocher obligatoire.

    Répondre à ce message

  • Bonjour,
    J’ai bâti formulaire public pour uploader des documents pdf et les ajouter à un objet éditorial.
    Pour cela j’utilise la fonction « ajouter_documents » du plugin Medias comme dans l’exemple.
    Je suis tombé sur un comportement inattendu : si un utilisateur n’est pas identifié, les fichiers sont uploadé correctement dans la médiathèque, mais le lien entre les documents et l’objet éditorial (dans la table spip_documents_liens) ne se fait pas.
    Si l’auteur est identifié tout fonctionne correctement.
    Est-ce que quelqu’un aurait une idée d’où peut venir le problème ?
    Merci

    Répondre à ce message

  • 4

    Bonjour,
    J’ai bien vu que CVT Upload permet d’ajouter des fichiers en téléchargement sans problème avec FORMIDABLE
    J’ai installé INSCRIPTION3 et Champs Extras .
    Or je n’ai pas la possibilité d’ajouter des fichiers, depuis Champs Extras
    Comment faire ?

    • cvt upload est là pour permettre à des plugins d’envoyer des fichiers. le traitement des fichiers se fait ensuite niveau plugin.

      Formidable a été adapté pour cela. Pas champ extra. Il y a une personne qui m’a contacté il y a peu, qui avait l’air intéressé par améliorer champ extra pour cela, mais pour le moment je n’ai pas de nouvelle....

    • Merci Maïeul pour ce retour rapide.
      C’est certain qu’une adaptation de Champs Extras serait utile.

    • Sauf que comme discuté avec JLuc plusieurs fois, ce n’est pas trivial du tout de décider quoi faire. Un champ extra c’est un champ précis avec un nom précis, ce n’est pas la médiathèque. Donc ça veut dire comment on stocke ce champ, ya quoi dans le champ SQL en base, où sera stocké le fichier uploadé, faut pouvoir visualiser le fichier de ce champ précis et quand on édite de l’existant faut pouvoir le supprimer et modifier, etc. Bref on ne sait pas encore vraiment ce que c’est censé faire dans les détails, ya pas mal de réfléchissage.

    • RastaPopoulos merci pour ton intervention.
      Voila ma réflexion.
      Aujourd’hui FORMIDABLE utilise CVT Upload, il crée un champ dans la table formulaires_reponses_champs avec un lien vers le fichier uploadé.
      Je pense que dans un premier temps un fonctionnement très similaire peut être intéressant.
      Création d’un champ « fichier » dans la table de l’objet dans laquelle on ajoute le champ extra
      _Le fichier uploadé suit le fonctionnement du stockage utilisé par Formidable. On pourrait le stocker dans config/fichiers/champextra (Formidable stocke dans config/fichiers/formidable)
      Comme dans Formidable quand on enregistre les réponses , on a un champ avec le lien vers le fichiers uploadé, on pourrait avoir dans l’objet concerné par ce champ extra, le lien vers le fichier uploadé.

      Donc un fonctionnement très proche de ce que l’on a actuellement avec FORMIDABLE.
      J’espère avoir formulé mon approche de manière compréhensible ;-)

    Répondre à ce message

  • 6

    Bonjour,

    Merci pour ce plugin très pratique !

    Une erreur ressort si le formulaire est posté sans fichier (unique) uploadé :

    Undefined offset: 0 in ---/spip/plugins/auto/cvtupload/v1.17.0/inc/cvtupload.php on line 171

    Il me semble que ceci résoudrait le problème :

    	if ( !empty( $infos) && $fichier_unique == true) {
    		$infos = $infos[0];
    	}
    • Merci, c’est corrigé dans la version 1.17.1 qui sera bientot disponible en zip.

    • Super !
      Du coup, puisque j’y suis :

      Dans inc-cvtupload-fichier.html -> une coquille Ligne17 avec

      [(#HTML5|oui)[ accept="(#GET{mime,''})"]]

      au lieu de

      [(#HTML5|oui)[ accept="(#ENV{mime,''})"]]

      Enfin, dans les exemples fournis, si fichier unique

      #SET{name,seul}
      name="#GET{name}"

      Et bien, cela plante au moment de verifier
      Saisie insère bien name avec un tableau

      name="#ENV{nom}\[[(#VALEUR|moins{1})]\]"
    • le fichier unique devrait passer normalement... il faut qu’on voit là où cela merdouille, mais les deux cas devraient pouvoir ce gerer : tableau ou pas.

    • Et bien, cela plante au moment de verifier
      Saisie insère bien name avec un tableau

      je n’ai aucun plantage. Pouvez vous me décrir plus précisement ce que vous faites ? que je puissse reproduire.

    • Configuration :

      SPIP 3.2.4
      CVTUPLOAD 1.17.0
      SAISIES 3.19.5
      VERIFIER 1.9.2

      HTML :

      <div class="editer editer_justificatif_upload[ (#ENV{justificatif}|non) obligatoire][ (#ENV**{erreurs}|table_valeur{justificatif_upload}|oui)erreur]">
        <label for="justificatif_upload"><:adherent:champ_justificatif_label:><span class='obligatoire'> <span>(*)</span></span></label>[
        <span class='erreur_message'>(#ENV**{erreurs}|table_valeur{justificatif_upload})</span>]
        <div class="file choix">
          <input type="file" class="file" name="justificatif_upload" id="justificatif_upload"[ (#ENV{justificatif}|non) required] accept="application/pdf" />
        </div>
      </div>

      Extrait de mon tableau de saisie :

      array(
        'saisie' 	=> 'fichiers',
        'options' => array(
          'nom' 				=> 'justificatif_upload',
          'label'			 	=> _T('adherent:champ_justificatif_label'),
          'nb_fichiers' => 1
        ),
        'verifier' => array(
          'type'=> 'fichiers',
          'options' => array(
            'taille_max' => 500,
            'mime' 	=>'specifique',
            'mime_specifique' => array('application/pdf')
          )
        )
      ),

      Dans la fonction vérifier

      $erreurs = array();
      $erreurs_par_fichier = array();
      
      $saisies = formulaires_editer_adherent_saisies_dist();
      
      $saisies_verifier = saisies_verifier($saisies,true,$erreurs_par_fichier);
      
      foreach ($saisies_verifier as $champ => $erreur) { 
        cvtupload_nettoyer_files_selon_erreurs($champ, $erreurs_par_fichier[$champ]);
      }

      Si je charge un fichier supérieur à 500 Mo :

      Erreur inattendue puis

      Fatal error: Uncaught Error: Cannot unset string offsets ----/spip/plugins/auto/cvtupload/v1.17.0/inc/cvtupload.php on line 250
      ( ! ) Error: Cannot unset string offsets in ----/spip/plugins/auto/cvtupload/v1.17.0/inc/cvtupload.php on line 250 

      J’ai l’impression que le problème vient de verifier

      Si je désactive toutes les options dans le tableau de saisie et que je passe par la fonction vérifier du formulaire

      $verifier = charger_fonction('verifier', 'inc', true);
      $options = array(
                      'mime' => 'specifique',
      		'mime_specifique' => array('application/pdf'),
      		'taille_max' => 500, // en kio
      );
      
      if ($erreur = $verifier($_FILES['justificatif_upload'], 'justificatif_upload', $options)) {
        // renvoyer l'erreur dans le formulaire
        $erreurs['justificatif_upload'] = $erreur;
        // supprimer le fichier en erreur dans _FILES
        cvtupload_nettoyer_files_selon_erreurs('justificatif_upload',$erreur);
      }

      Il ne se passe rien : aucune vérification de la taille du fichier

    Répondre à ce message

  • 2

    Merci. Excellent. Donc nous pourrions intégrer ce plugin pour laisser uploader des fichiers via la fabrique, pour construire un plugin avec une telle fonction...est-ce que quelqu’un peut partager un tel tutoriel.

    • Uploader des fichiers via la Fabrique ? Qu’est-ce que ça peut bien vouloir dire ? :)

      Ce plugin est uniquement pour les dévs, et il ne fait rien des fichiers, ça ne dit pas qu’est-ce qui sera fait des fichiers ensuite dans le traitement. Ça gère juste la mise en mémoire durant la vérification.

    • Oui, justement il est pour le devs, donc je me disais que cela serait plutôt bien de pouvoir coupler ses fonctionnalités de gère juste la mise en mémoire durant la vérification pour avoir un bon fonctionnement de la fonction upload...je ne sais si c’est plus clair comme cela ou pas.

      Merci pour le plugin.

      Bonne journée.

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom