diff --git a/formulaires/creer_feed_territoires.html b/formulaires/creer_feed_territoires.html
index 2b67cc3dcdd4fbe53a618b8c4ea7c51d35362920..cb25283c71fe51d59576d38c355baae97fb27110 100644
--- a/formulaires/creer_feed_territoires.html
+++ b/formulaires/creer_feed_territoires.html
@@ -38,8 +38,8 @@
 					defaut=#ENV{_type_source_defaut}
 				})]
 
-				[(#SAISIE{input, fichier_source,
-					type=file,
+				[(#SAISIE{fichiers, fichier_source,
+					nb_fichiers=1,
 					explication=<:territoires_stats:explication_feed_fichier:>,
 					label=<:territoires_stats:label_feed_fichier:>,
 					conteneur_class=bloc_fichier_source,
@@ -93,10 +93,10 @@
 
 		function afficher_bloc_source(type_source) {
 			if (type_source === 'api') {
-				jQuery("div.bloc_fichier_source").hide();
+				jQuery("fieldset.bloc_fichier_source").hide();
 				jQuery("div.bloc_url_source").show();
 			} else {
-				jQuery("div.bloc_fichier_source").show();
+				jQuery("fieldset.bloc_fichier_source").show();
 				jQuery("div.bloc_url_source").hide();
 			}
 		}
diff --git a/formulaires/creer_feed_territoires.php b/formulaires/creer_feed_territoires.php
index 4c093315072abac85ec7b352b8f41ed6af0c282c..ff2a307149a9445a08d4af3e3ba6cfd1383294d5 100644
--- a/formulaires/creer_feed_territoires.php
+++ b/formulaires/creer_feed_territoires.php
@@ -15,11 +15,11 @@ function formulaires_creer_feed_territoires_charger() : array {
 	// Etape 1
 	// Récupération des saisies éventuelles de l'étape 1
 	$valeurs = [
-		'type'       => _request('type') ?? '',
+		'type'        => _request('type') ?? '',
 		'type_source' => _request('type_source') ?? '',
-		'fichier_source' => _request('fichier_source') ?? '',
-		'url_source' => _request('url_source') ?? '',
-		'extra' => _request('extra') ?? '',
+		'_fichiers'   => _request('_fichiers') ?? '',
+		'url_source'  => _request('url_source') ?? '',
+		'extra'       => _request('extra') ?? '',
 		'titre_extra' => _request('titre_extra') ?? '',
 	];
 	include_spip('inc/config');
@@ -73,6 +73,9 @@ function formulaires_creer_feed_territoires_charger() : array {
 	// -- options de décodage : délimiteur si fichier CSV, racine à partir de laquelle paramétrer le mapping
 	$valeurs['_label_decodage'] = _request('_label_decodage');
 	$valeurs['_explication_decodage'] = _request('_explication_decodage');
+	// -- explication du mapping dépendant du format de la source
+	$valeurs['_explication_mapping_code'] = _request('_explication_mapping_code');
+	$valeurs['_explication_mapping_valeur'] = _request('_explication_mapping_valeur');
 	// -- Type de code de territoire utilisé dans le jeu de données
 	$valeurs['_types_code'] = _request('_types_code');
 	$valeurs['_type_code_defaut'] = _request('_type_code_defaut');
@@ -87,7 +90,6 @@ function formulaires_creer_feed_territoires_charger() : array {
 	$valeurs['mapping_valeur'] = _request('mapping_valeur') ?? '';
 	$valeurs['feed_id'] = _request('feed_id') ?? '';
 	$valeurs['titre'] = _request('titre') ?? '';
-	$valeurs['description'] = _request('description') ?? '';
 
 	// Préciser le nombre d'étapes du formulaire
 	$valeurs['_etapes'] = 2;
@@ -95,6 +97,15 @@ function formulaires_creer_feed_territoires_charger() : array {
 	return $valeurs;
 }
 
+/**
+ * Identification des saisies Fichiers du formulaire :
+ *
+ * @return array Tableau des variables des saisies Fichiers.
+ */
+function formulaires_creer_feed_territoires_fichiers() {
+	return ['fichier_source'];
+}
+
 /**
  * Vérification du formulaire :.
  *
@@ -137,16 +148,17 @@ function formulaires_creer_feed_territoires_verifier_1() : array {
 			$erreurs['url_source'] = _T('territoires_stats:erreur_feed_url_source');
 		}
 	} else {
-		$variable_source = 'fichier_source';
-		if (empty($_FILES[$variable_source]['name'])) {
+		$fichiers = _request('_fichiers');
+		$variable_source = $fichiers['fichier_source'][0];
+		if (empty($variable_source['name'])) {
 			// Aucun fichier choisi.
-			$erreurs[$variable_source] = _T('info_obligatoire');
+			$erreurs['fichier_source'] = _T('info_obligatoire');
 		} elseif (
-			empty($_FILES[$variable_source]['type'])
-			or (!in_array($_FILES[$variable_source]['type'], ['application/json', 'application/xml', 'text/csv']))
+			empty($variable_source['mime'])
+			or (!in_array($variable_source['mime'], ['application/json', 'application/xml', 'text/csv']))
 		) {
 			// Format de fichier invalide
-			$erreurs[$variable_source] = _T('territoires_stats:erreur_feed_format_fichier');
+			$erreurs['fichier_source'] = _T('territoires_stats:erreur_feed_format_fichier');
 		}
 	}
 
@@ -184,15 +196,19 @@ function formulaires_creer_feed_territoires_verifier_1() : array {
 		$format = 'json';
 		if ($type_source === 'file') {
 			// Extraire l'extension pour déterminer l'option de décodage à présenter
-			[, $format] = explode('/', $_FILES[$variable_source]['type']);
+			[, $format] = explode('/', $variable_source['mime']);
 		}
 		set_request('_format_source', $format);
 		if ($format === 'csv') {
 			set_request('_label_decodage', _T('territoires_stats:label_feed_decodage_delimiteur'));
 			set_request('_explication_decodage', _T('territoires_stats:explication_feed_decodage_delimiteur'));
+			set_request('_explication_mapping_code', _T('territoires_stats:explication_feed_mapping_code_csv'));
+			set_request('_explication_mapping_valeur', _T('territoires_stats:explication_feed_mapping_valeur_csv'));
 		} else {
 			set_request('_label_decodage', _T('territoires_stats:label_feed_decodage_racine'));
 			set_request('_explication_decodage', _T('territoires_stats:explication_feed_decodage_racine'));
+			set_request('_explication_mapping_code', _T('territoires_stats:explication_feed_mapping_code'));
+			set_request('_explication_mapping_valeur', _T('territoires_stats:explication_feed_mapping_valeur'));
 		}
 
 		// -- Identifiant proposé pour le feed
@@ -227,11 +243,13 @@ function formulaires_creer_feed_territoires_verifier_2() : array {
 	$mapping_valeur = _request('mapping_valeur');
 
 	// Vérification de la saisie des mappings qui ne doivent contenir qu'un ou plusieurs mots séparés par des '/'
-	if (!preg_match('#^[\w/]+$#i', $mapping_code)) {
-		$erreurs['mapping_code'] = _T('territoires_stats:erreur_feed_mapping_code');
-	}
-	if (!preg_match('#^[\w/]+$#i', $mapping_valeur)) {
-		$erreurs['mapping_valeur'] = _T('territoires_stats:erreur_feed_mapping_valeur');
+	if ($format_source !== 'csv') {
+		if (!preg_match('#^[\w/]+$#i', $mapping_code)) {
+			$erreurs['mapping_code'] = _T('territoires_stats:erreur_feed_mapping_code');
+		}
+		if (!preg_match('#^[\w/]+$#i', $mapping_valeur)) {
+			$erreurs['mapping_valeur'] = _T('territoires_stats:erreur_feed_mapping_valeur');
+		}
 	}
 
 	// Vérification du décodage en fonction du type de source
@@ -273,9 +291,6 @@ function formulaires_creer_feed_territoires_traiter() : array {
 	$type = _request('type');
 	$pays = _request('pays_' . $type) ?? '';
 	$type_source = _request('type_source');
-	$source = $type_source === 'api'
-		? _request('url_source')
-		: basename($_FILES['fichier_source']['name']);
 	$extra = _request('extra');
 //	$titre_extra = _request('titre_extra');
 	$format_source = _request('format_source');
@@ -287,7 +302,6 @@ function formulaires_creer_feed_territoires_traiter() : array {
 	$mapping_valeur = _request('mapping_valeur');
 	$id_feed = _request('feed_id');
 	$titre_feed = _request('titre');
-	$description_feed = _request('description') ?? '';
 
 	// Initialisation du YAML à partir du template
 	include_spip('inc/yaml');
@@ -298,7 +312,6 @@ function formulaires_creer_feed_territoires_traiter() : array {
 	// On considère que toutes les vérifications ont été faites et que donc les variables saisies sont cohérentes
 	// -- identification
 	$description_yaml['title'] = $titre_feed;
-	$description_yaml['description'] = $description_feed;
 	// -- catégorisation : seuls les tags sont à mettre à jour
 	$description_yaml['tags']['type'] = $type;
 	$description_yaml['tags']['pays'] = $pays;
@@ -308,8 +321,8 @@ function formulaires_creer_feed_territoires_traiter() : array {
 		// Le code primaire est utilisé dans jeu de données, il n'est pas utile de passer par un code alternatif
 		// - le champ `code_feed` est donc inutile
 		$description_yaml['mapping']['basic_fields']['iso_territoire'] = $mapping_code;
-		unset($description_yaml['mapping']['basic_fields']['code_feed']);
-		unset($description_yaml['mapping']['unused_fields']);
+		unset($description_yaml['mapping']['basic_fields']['code_feed'], $description_yaml['mapping']['unused_fields']);
+
 	} else {
 		// Le jeu de données utilise un code alternatif au code primaire
 		// - le champ `code_feed` est donc nécessaire temporairement
@@ -318,49 +331,57 @@ function formulaires_creer_feed_territoires_traiter() : array {
 	$description_yaml['mapping']['basic_fields']['valeur'] = $mapping_valeur;
 	$description_yaml['mapping']['static_fields']['extra'] = $extra;
 	// -- la source : pour l'instant les crédits ne sont pas supportés, elle porte toujours l'id `source_1`
-	$description_yaml['sources_basic']['source_1']['source']['type'] = $type_source;
-	$description_yaml['sources_basic']['source_1']['source']['format'] = $format_source;
-	$description_yaml['sources_basic']['source_1']['source']['uri'] = $source;
+	//    L'uri sera remplie plus avant pour traiter le cas du fichier télécharger à copier dans l'emplacement final
+	$id_source = 'basic_1';
+	$description_yaml['sources_basic'][$id_source]['source']['type'] = $type_source;
+	$description_yaml['sources_basic'][$id_source]['source']['format'] = $format_source;
 	if ($format_source === 'csv') {
-		unset($description_yaml['sources_basic']['source_1']['decoding']['root_node']);
-		$description_yaml['sources_basic']['source_1']['decoding']['delimiter'] = $decodage;
+		unset($description_yaml['sources_basic'][$id_source]['decoding']['root_node']);
+		$description_yaml['sources_basic'][$id_source]['decoding']['delimiter'] = $decodage;
 	} else {
-		unset($description_yaml['sources_basic']['source_1']['decoding']['delimiter']);
-		$description_yaml['sources_basic']['source_1']['decoding']['root_node'] = $decodage;
+		unset($description_yaml['sources_basic'][$id_source]['decoding']['delimiter']);
+		$description_yaml['sources_basic'][$id_source]['decoding']['root_node'] = $decodage;
 	}
 
-	// Ecriture de la source si elle est au format fichier
-	if ($type_source === 'file') {
-		// Récupération du fichier qui est stocké temporairement dans tmp/ en attendant le chargement du feed
-		// -- Création du répertoire d'upload
-		$dir = sous_repertoire(_DIR_TMP, 'territoires_stats');
-
-		// -- Détermination du nom du fichier temporaire de façon à ce qu'il soit unique.
-		$hash = md5("{$format_source}-" . $GLOBALS['visiteur_session']['id_auteur'] . time());
-		$fichier = $dir . $hash . '-' . $_FILES['fichier_source']['name'];
-
-		// -- Déplacement du fichier téléchargé dans la destination choisie.
-		if (move_uploaded_file($_FILES['fichier_source']['tmp_name'], $fichier)) {
-			// -- Lecture et suppression du fichier temporaire
-			include_spip('inc/flock');
-			lire_fichier($fichier, $contenu_source);
+	// Identification de la source et mise à jour dans la description YAML
+	// -- si la source est un fichier, on le copie dans le dossier du feed
+	$source = '';
+	if ($type_source === 'api') {
+		$source = _request('url_source');
+	} else {
+		// Récupération du fichier qui est stocké temporairement dans tmp/ par CVT Upload
+		$fichiers = _request('_fichiers');
+		$fichier = $fichiers['fichier_source'][0]['tmp_name'];
+
+		// Lecture du fichier temporaire
+		include_spip('inc/flock');
+		lire_fichier($fichier, $contenu_source);
+
+		// Stockage de la source dans son emplacement final
+		$ressource = [
+			'type' => "source_{$format_source}",
+			'id'   => $id_source
+		];
+		if ($fichier_source = feed_ressource_ecrire('territoires_stats', $id_feed, $ressource, $contenu_source)) {
+			// -- extraire l'uri pour la description YAML
+			$source = basename($fichier_source);
+			// -- suppression du fichier temporaire
 			@unlink($fichier);
-
-			// Stockage de la source dans son emplacement final
-			$type_ressource = "source_{$format_source}";
-			if (!feed_ressource_ecrire('territoires_stats', $id_feed, $type_ressource, $contenu_source)) {
-				$retour['message_erreur'] = _T('territoires_stats:erreur_recupération_source');
-			}
-		}
-		else {
-			$retour['message_erreur'] = _T('territoires_stats:erreur_recupération_source');
+		} else {
+			$retour['message_erreur'] = _T('territoires_stats:erreur_recuperation_source');
 		}
 	}
 
 	if (empty($retour['message_erreur'])) {
+		// On finalise la description du YAML avec la source
+		$description_yaml['sources_basic'][$id_source]['source']['uri'] = $source;
+
 		// Ecriture du YAML
 		include_spip('inc/ezmashup_feed');
-		if (feed_ressource_ecrire('territoires_stats', $id_feed, 'config', $description_yaml)) {
+		$ressource = [
+			'type' => 'config',
+		];
+		if (feed_ressource_ecrire('territoires_stats', $id_feed, $ressource, $description_yaml)) {
 			// Insertion du YAML en base de données
 			feed_charger('territoires_stats');
 		} else {
diff --git a/formulaires/creer_feed_territoires_2.html b/formulaires/creer_feed_territoires_2.html
index 191697fa014aeb680f2eec994a0559a354ecf926..c12a1138d1712e523a3054e5305e5f7f6984c135 100644
--- a/formulaires/creer_feed_territoires_2.html
+++ b/formulaires/creer_feed_territoires_2.html
@@ -22,13 +22,13 @@
 				})]
 
 				[(#SAISIE{input, mapping_code,
-					explication=<:territoires_stats:explication_feed_mapping_code:>,
+					explication=#ENV{_explication_mapping_code},
 					label=<:territoires_stats:label_feed_mapping_code:>,
 					obligatoire=oui,
 				})]
 
 				[(#SAISIE{input, mapping_valeur,
-					explication=<:territoires_stats:explication_feed_mapping_valeur:>,
+					explication=#ENV{_explication_mapping_valeur},
 					label=<:territoires_stats:label_feed_mapping_valeur:>,
 					obligatoire=oui,
 				})]
@@ -51,12 +51,6 @@
 					label=<:territoires_stats:label_feed_titre:>,
 					obligatoire=oui,
 				})]
-
-				[(#SAISIE{textarea, description,
-					explication=<:territoires_stats:explication_feed_description:>,
-					label=<:territoires_stats:label_feed_description:>,
-					rows=5,
-				})]
 		</fieldset>
 
 		[(#SAISIE{hidden, format_source,
diff --git a/lang/territoires_stats_fr.php b/lang/territoires_stats_fr.php
index 9e87d20f9c32ab8f60130a87ded4a255b7c1d6f8..faea9ababf96ca0616349b2376719bc55d0552c1 100644
--- a/lang/territoires_stats_fr.php
+++ b/lang/territoires_stats_fr.php
@@ -20,6 +20,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
 	'explication_feed_decodage_racine' => 'Cet index racine représente la partie commune qui est appliquée au mapping du code et de la valeur statistique dans le tableau des données source. Il est exprimé sous la forme index1/index2/index3',
 	'explication_feed_mapping_code' => 'Cet index racine représente la partie spécifique permettant d\'accéder au code de territoire dans le tableau des données source. Il est exprimé sous la forme index1/index2/index3',
 	'explication_feed_mapping_valeur' => 'Cet index racine représente la partie spécifique permettant d\'accéder à la valeur statistique dans le tableau des données source. Il est exprimé sous la forme index1/index2/index3',
+	'explication_feed_mapping_code_csv' => 'Cet index racine représente le nom de la colonne correspondant au code de territoire dans le le fichier CSV.',
+	'explication_feed_mapping_valeur_csv' => 'Cet index racine représente le nom de la colonne correspondant à la valeur statistique dans le fichier CSV.',
 
 	// I
 	'icone_creer_feed' => 'Créer un jeu de données',