diff --git a/controleurs/formulaires_reponses_champ.html b/controleurs/formulaires_reponses_champ.html
index c6b8c9300580235a8a3d3d9ef9ab332c2de719cf..a48c5542ab11b4e784ec54ce307a10599c541ba1 100644
--- a/controleurs/formulaires_reponses_champ.html
+++ b/controleurs/formulaires_reponses_champ.html
@@ -1,5 +1,5 @@
 <div style="width:#ENV{largeur}px;#ENV{style};background-color:inherit;">
 	<div class="editer-groupe">
-		#GENERER_SAISIES{#ENV{_saisies}}
+		#ENV**{saisie_html}
 	</div>
 </div>
diff --git a/controleurs/formulaires_reponses_champ.php b/controleurs/formulaires_reponses_champ.php
index 7d5034287126300a5a8409fd468603f2295c4142..0f183eb4bd8f5fcdc1e7f7ef5e853e1c5d4ab6d4 100644
--- a/controleurs/formulaires_reponses_champ.php
+++ b/controleurs/formulaires_reponses_champ.php
@@ -42,16 +42,67 @@ function controleurs_formulaires_reponses_champ_dist($regs, $c = null) {
 	);
 	$key = $n->key;
 
+
+	$valeur = formidable_deserialize($valeur);
+
 	unset($saisie['options']['label']);
 	unset($saisie['options']['explication']);
 	unset($saisie['options']['class']);
 	unset($saisie['options']['conteneur_class']);
 
+
 	// Crayons utilise son propre formalisme pour le 'name' des saisies.
 	$nom_crayons = 'content_' . $key . '_valeur';
 	$saisie['options']['nom'] = $nom_crayons;
-	$valeur = formidable_deserialize($valeur);
-	$contexte = ['_saisies' => [$saisie], $nom_crayons =>  $valeur];
+	$pre_saisies = '';
+	$saisie_html = saisies_generer_html($saisie, [$nom_crayons => $valeur]);
+
+	// Cas spécial de la saisie fichier, on précharge
+	if (saisies_saisie_est_fichier($saisie) && is_array($valeur)) {
+		include_spip('inc/cvtupload');
+		include_spip('inc/formidable_fichiers');
+		include_spip('inc/filtres');
+
+		$precharger_fichiers = charger_fonction('cvtupload_precharger_fichiers', 'inc');
+		$fichiers = [];
+		foreach ($valeur as $f) {
+			$fichiers[] = [
+				'chemin' => formidable_generer_chemin_fichier([
+					'formulaire' => $data['id_formulaire'],
+					'reponse' => $data['id_formulaires_reponse'],
+					'saisie' => $nom,
+					'fichier' => $f['nom']
+				]),
+				'url' => formidable_generer_url_action_recuperer_fichier(
+					$data['id_formulaire'],
+					$data['id_formulaires_reponse'],
+					$nom,
+					$f['nom']
+				)
+			];
+		}
+		$fichiers_precharges = $precharger_fichiers([$nom_crayons => $fichiers], 'formidable_crayons');
+
+		$pre_saisie = cvtupload_generer_hidden($fichiers_precharges);
+		if ($pre_saisie) {
+			$cvtupload_html = cvtupload_generer_html($fichiers_precharges);
+			$cvtupload_html = $cvtupload_html[$nom_crayons];
+			foreach ($cvtupload_html as $cle => $html) {
+				$saisie_html = preg_replace(
+					"#<input[^>]*name=['\"]{$nom_crayons}(?:\&\#91;|\[){$cle}(?:\&\#93;|\])[^>]*>#i",
+					$html,
+					$saisie_html
+				);
+			}
+			$saisie_html = $pre_saisie . $saisie_html;
+		}
+	}
+
+	$contexte = [
+		'saisie_html' => $saisie_html,
+	];
+
+
 	$html = $n->formulaire($contexte);
 
 	$status = $scripts = null;
@@ -62,5 +113,6 @@ function controleurs_formulaires_reponses_champ_dist($regs, $c = null) {
 		$scripts = '<link rel="stylesheet" type="text/css" href="' . find_in_path('css/ui/jquery-ui.css') . '" />';
 	}
 
+
 	return [$html . $scripts, $status];
 }
diff --git a/formidable_pipelines.php b/formidable_pipelines.php
index 4b6a625087d9214246e9e6b2c0220d424b0f3f51..d20a997d3ed318a2b70aec94c23f63dd35c75e46 100644
--- a/formidable_pipelines.php
+++ b/formidable_pipelines.php
@@ -359,15 +359,17 @@ function formidable_crayons_verifier($flux) {
 	$id = $flux['args']['id'];
 	$valeur = $flux['args']['content']['valeur'];
 	$data = sql_fetsel(
-		['nom', 'saisies'],
+		['nom', 'saisies', 'f.id_formulaire', 'r.id_formulaires_reponse'],
 		['spip_formulaires_reponses_champs AS c', 'spip_formulaires_reponses AS r', 'spip_formulaires AS f'],
 		["id_formulaires_reponses_champ = $id",  'r.id_formulaires_reponse = c.id_formulaires_reponse', 'f.id_formulaire = r.id_formulaire']
 	);
 	include_spip('formidable_fonctions');
+
 	$saisies = formidable_deserialize($data['saisies']);
 	$saisie = saisies_chercher($saisies, $data['nom']);
+	$atrouver = 'content_' . $flux['args']['wid'] . '_valeur';
+
 	if (saisies_saisie_est_tabulaire($saisie)) {
-		$atrouver = 'content_' . $flux['args']['wid'] . '_valeur';
 		$valeur = saisies_request($atrouver);
 		$flux['data']['normaliser']['valeur'] = formidable_serialize($valeur);
 	}
@@ -380,6 +382,52 @@ function formidable_crayons_verifier($flux) {
 	} elseif (saisies_request($data['nom']) !== $valeur) {
 		$flux['data']['normaliser']['valeur'] = $normaliser;
 	}
+
+	if (!$erreur && saisies_saisie_est_fichier($saisie)) {
+		$flux = formidable_crayons_verifier_fichier($flux, $saisie, $data);
+	}
+	return $flux;
+}
+
+/**
+ *
+ * Vérification des crayons pour le cas d'une saisie de type fichier
+ * @param array $flux de formulaire
+ * @param array $saisie description de la saisie
+ * @param array $data données sur le champ, tirées de sql
+ * @return array $flux;
+**/
+function formidable_crayons_verifier_fichier(array $flux, array $saisie, array $data): array {
+	include_spip('inc/cvtupload');
+	include_spip('traiter/enregistrement');
+	include_spip('inc/formidable_fichiers');
+	include_spip('action/ajouter_documents');
+
+	$valeur = $flux['args']['content']['valeur'];
+	$nom_crayons = 'content_' . $flux['args']['wid'] . '_valeur';
+	$nom_saisie = $saisie['options']['nom'];
+
+	// Faire comme si on était un vrai formulaire CVT, et donc s'appuyer sur CVTupload qui va se charger de mettre les fichiers où il faut comme il faut
+	include_spip('cvtupload_pipelines');
+	cvtupload_formulaire_verifier([
+		'args' => [
+			'form' => 'formidable_crayons',
+			'args' => [$nom_crayons]
+		]
+	]);
+
+	if (isset($_FILES[$nom_crayons])) {
+		$_FILES[$nom_saisie] = $_FILES[$nom_crayons];
+	}
+	formidable_effacer_fichiers_champ($data['id_formulaire'], $data['id_formulaires_reponse'], $saisie['options']['nom']);
+	$valeur = traiter_enregistrement_fichiers($saisie, $data['id_formulaire'], $data['id_formulaires_reponse']);
+	if (is_array($valeur)) {
+		$valeur = formidable_serialize($valeur);
+	} else {
+		$valeur = formidable_serialize([]);
+	}
+	$flux['data']['normaliser']['valeur'] = $valeur;
+
 	return $flux;
 }
 
diff --git a/formulaires/formidable_crayons.php b/formulaires/formidable_crayons.php
new file mode 100644
index 0000000000000000000000000000000000000000..6acc98e4b06015ce9ea06c5394260a9406efb544
--- /dev/null
+++ b/formulaires/formidable_crayons.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * Déclaration des crayons "comme si c'était du cvt"
+ * pour CVT Upload
+ *
+ * @package SPIP\Formidable\Crayons
+ **/
+
+/**
+ * Déclarons un crayonnage de champ fichier comme si c'était un CVT
+ * @param string $nom_crayons
+ * @return array
+**/
+function formulaires_formidable_crayons_fichiers(string $nom_crayons): array {
+	return [$nom_crayons];
+}
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 2da450672dd75ed232ea7d4591a1fe5dabcefb12..4bf37214a30141f44eed3083b4f1146fdf89fb23 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -385,6 +385,21 @@ parameters:
 			count: 1
 			path: controleurs/formulaires_reponses_champ.php
 
+		-
+			message: "#^Function charger_fonction not found\\.$#"
+			count: 1
+			path: controleurs/formulaires_reponses_champ.php
+
+		-
+			message: "#^Function cvtupload_generer_hidden not found\\.$#"
+			count: 1
+			path: controleurs/formulaires_reponses_champ.php
+
+		-
+			message: "#^Function cvtupload_generer_html not found\\.$#"
+			count: 1
+			path: controleurs/formulaires_reponses_champ.php
+
 		-
 			message: "#^Function find_in_path not found\\.$#"
 			count: 1
@@ -392,7 +407,7 @@ parameters:
 
 		-
 			message: "#^Function include_spip not found\\.$#"
-			count: 2
+			count: 5
 			path: controleurs/formulaires_reponses_champ.php
 
 		-
@@ -400,6 +415,16 @@ parameters:
 			count: 1
 			path: controleurs/formulaires_reponses_champ.php
 
+		-
+			message: "#^Function saisies_generer_html not found\\.$#"
+			count: 1
+			path: controleurs/formulaires_reponses_champ.php
+
+		-
+			message: "#^Function saisies_saisie_est_fichier not found\\.$#"
+			count: 1
+			path: controleurs/formulaires_reponses_champ.php
+
 		-
 			message: "#^Function sql_fetsel not found\\.$#"
 			count: 1
@@ -880,6 +905,11 @@ parameters:
 			count: 1
 			path: formidable_pipelines.php
 
+		-
+			message: "#^Function cvtupload_formulaire_verifier not found\\.$#"
+			count: 1
+			path: formidable_pipelines.php
+
 		-
 			message: "#^Function id_table_objet not found\\.$#"
 			count: 1
@@ -887,7 +917,7 @@ parameters:
 
 		-
 			message: "#^Function include_spip not found\\.$#"
-			count: 7
+			count: 12
 			path: formidable_pipelines.php
 
 		-
@@ -945,6 +975,11 @@ parameters:
 			count: 2
 			path: formidable_pipelines.php
 
+		-
+			message: "#^Function saisies_saisie_est_fichier not found\\.$#"
+			count: 1
+			path: formidable_pipelines.php
+
 		-
 			message: "#^Function saisies_saisie_est_tabulaire not found\\.$#"
 			count: 1
@@ -2305,6 +2340,11 @@ parameters:
 			count: 2
 			path: traiter/enregistrement.php
 
+		-
+			message: "#^Function saisies_saisie_est_fichier not found\\.$#"
+			count: 1
+			path: traiter/enregistrement.php
+
 		-
 			message: "#^Function saisies_saisie_est_tabulaire not found\\.$#"
 			count: 1