Téléversement de fichier Shiny : lire un CSV téléversé avec fileInput en R

Ajoutez un contrôle fileInput(), lisez ce que vous donne le data frame de téléversement, chargez le CSV ou Excel téléversé depuis son datapath, protégez avec req(), acceptez des fichiers multiples et relevez la limite de taille.

Programming
Shiny

Un contrôle fileInput() permet aux utilisateurs d’apporter leurs propres données dans une application Shiny. Cette leçon couvre tout le workflow de téléversement : ce que reçoit le server (un data frame de name, size, type et datapath), la lecture du fichier téléversé depuis son datapath temporaire avec read.csv() ou readxl::read_excel(), la protection avec req() pour que l’application ne génère pas d’erreur avant qu’un fichier soit choisi, la gestion des fichiers multiples, et le relèvement de la limite de taille de téléversement avec shiny.maxRequestSize.

Date de publication

28 juin 2026

Modifié

7 juillet 2026

AstucePoints clés
  • fileInput() ajoute le contrôle de téléversement. Mettez fileInput("file", "Choose a file") dans le ui ; l’utilisateur choisit un fichier et Shiny remet au server tout ce qu’il faut pour le lire.
  • Le server reçoit un petit data frame, pas le fichier. input$file a les colonnes name, size, type et datapath — lisez le fichier depuis input$file$datapath, le chemin temporaire sur le disque, jamais depuis le name d’origine.
  • Choisissez le lecteur selon l’extension. read.csv() pour CSV/texte, readxl::read_excel() pour Excel ; aiguillez avec tools::file_ext() quand un même contrôle accepte plusieurs formats.
  • Protégez avec req(input$file). Avant que l’utilisateur ne téléverse, input$file vaut NULL ; req() fait attendre le reactive sans bruit au lieu de générer une erreur au démarrage.
  • Des fichiers multiples donnent un data frame à plusieurs lignes. fileInput(..., multiple = TRUE) transforme input$file en une ligne par fichier ; bouclez sur input$file$datapath avec lapply() pour tous les lire.
  • Relevez la limite de taille et restreignez les types. options(shiny.maxRequestSize = 30*1024^2) relève le plafond par défaut de 5 Mo ; accept = c(".csv") limite ce que le sélecteur propose.

Introduction

Toutes les applications jusqu’ici ont travaillé sur des données que vous aviez livrées avec elles — mtcars, iris, un data frame intégré au server. Dès que vous voulez que les utilisateurs analysent leurs propres données, il vous faut un contrôle de téléversement : un bouton qui leur laisse choisir un fichier, et du code server qui le lit. Dans Shiny, c’est fileInput() côté ui et input$file$datapath côté server.

L’idée qui fait trébucher : quand un fichier est téléversé, le server ne reçoit ni le contenu du fichier ni son emplacement d’origine — il reçoit un petit data frame qui décrit le téléversement, dont un chemin temporaire sur le disque où Shiny l’a enregistré. Vous lisez ce chemin. Cette leçon parcourt tout le workflow — le contrôle, ce que reçoit le server, la lecture de CSV et d’Excel, la protection par req(), les fichiers multiples et la limite de taille — pour qu’un téléversement alimente directement les sorties table et graphique que vous connaissez déjà.

NoteCopiez n’importe quel bloc dans app.R et exécutez-le en local

Le code de cette page n’est pas exécuté ici — une application Shiny a besoin d’une session R active, elle ne peut donc pas tourner dans une page web statique. Copiez n’importe quel bloc dans un fichier app.R et exécutez-le en local avec shiny::runApp() (ou cliquez sur Run App dans RStudio). Chaque extrait s’insère dans un ui fluidPage() et la fonction server ; installez readxl une fois avec install.packages("readxl") pour les exemples Excel.

Le contrôle fileInput()

Ajoutez le bouton de téléversement avec fileInput("id", "Label"). Le premier argument est l’inputId que vous lirez sur le server ; le reste contrôle ce que le sélecteur propose. Les deux arguments auxquels vous recourez le plus sont accept (quels types de fichiers la boîte de dialogue affiche) et multiple (un seul fichier ou plusieurs).

library(shiny)

ui <- fluidPage(
  titlePanel("Upload a CSV"),
  fileInput(
    "file", "Choose a CSV file",
    accept = c(".csv", ".txt")     # restrict the picker to these extensions
  ),
  tableOutput("preview")
)

accept est une indication pour la boîte de dialogue de fichiers — elle grise les fichiers qui ne correspondent pas mais ne garantit pas ce qui arrive, vérifiez donc quand même l’extension côté server (section suivante). Laissez accept de côté pour tout autoriser. Cela rend un bouton « Browse… » standard avec une barre de progression ; le choix de l’utilisateur arrive sur le server sous la forme input$file.

Ce que vous donne input$file

Quand l’utilisateur choisit un fichier, input$file est un data frame — et non le contenu du fichier. Il a une ligne par fichier téléversé et quatre colonnes qui décrivent chacun :

Colonne Ce qu’elle contient
name le nom de fichier d’origine sur la machine de l’utilisateur — "sales.csv"
size la taille du fichier en octets
type le type MIME rapporté par le navigateur — "text/csv" (ne vous y fiez pas)
datapath le chemin temporaire où Shiny a enregistré le téléversement — lisez celui-ci

La colonne qui compte, c’est datapath : Shiny copie le téléversement dans un fichier temporaire et datapath est l’endroit où il réside sur le server. Vous lisez les données depuis input$file$datapath, jamais depuis name. Le name d’origine pointe vers un fichier sur l’ordinateur de l’utilisateur que le server ne peut pas voir — le lire échoue.

server <- function(input, output, session) {
  output$info <- renderPrint({
    req(input$file)                  # wait until a file is uploaded
    input$file                       # the upload data frame: name, size, type, datapath
  })
}

Pour un téléversement unique, input$file$name, input$file$size et input$file$datapath vous donnent chacun la valeur de ce fichier-là. Affichez name et size à l’utilisateur ; recourez à datapath pour ouvrir réellement le fichier.

Lire le fichier téléversé

Le chemin en main, la lecture est du R ordinaire. Tout le motif de téléversement est protéger, puis lire depuis datapath à l’intérieur d’un reactive() pour que chaque sortie partage un seul data frame analysé.

server <- function(input, output, session) {

  # read ONCE from the temporary path, reused by every output
  uploaded <- reactive({
    req(input$file)                          # no file yet -> wait
    read.csv(input$file$datapath)            # read from datapath, NOT input$file$name
  })

  output$preview <- renderTable({ head(uploaded()) })   # first rows
  output$summary <- renderPrint({ summary(uploaded()) }) # column summary
}

read.csv(input$file$datapath) ouvre le fichier temporaire que Shiny a enregistré et renvoie un data frame ; head() et summary() travaillent ensuite dessus comme sur n’importe quel autre. Le reactive met en cache les données analysées pour que l’aperçu et le résumé ne relisent pas chacun le fichier. Passez les arguments habituels de read.csv()header, sep, stringsAsFactors — directement quand le format les requiert.

Fichiers Excel avec readxl

CSV utilise base R ; Excel a besoin du readxl package. Le seul changement est le lecteur — toujours pointé sur input$file$datapath :

library(readxl)

uploaded <- reactive({
  req(input$file)
  readxl::read_excel(input$file$datapath)   # .xlsx / .xls from the same datapath
})

read_excel() lit la première feuille par défaut ; passez sheet = pour en choisir une autre. Pensez à élargir accept aux extensions Excel sur le contrôle : fileInput("file", "Choose a file", accept = c(".xlsx", ".xls")).

Choisir le lecteur selon l’extension

Quand un même contrôle accepte plusieurs formats, aiguillez selon l’extension du fichier. tools::file_ext() l’extrait du name d’origine, et switch() route vers le bon lecteur :

uploaded <- reactive({
  req(input$file)
  ext <- tools::file_ext(input$file$name)        # "csv", "xlsx", ...
  switch(ext,
    csv  = read.csv(input$file$datapath),
    txt  = read.csv(input$file$datapath, sep = "\t"),
    xlsx = readxl::read_excel(input$file$datapath),
    xls  = readxl::read_excel(input$file$datapath),
    validate("Please upload a .csv or Excel file.")  # anything else -> a message
  )
})

Prenez l’extension depuis name (le chemin que Shiny attribue à datapath n’a pas d’extension significative), mais lisez toujours le contenu depuis datapath. Le repli validate() affiche à l’utilisateur un message clair pour un type non pris en charge plutôt qu’une erreur brute — une référence rapide pour savoir quel lecteur gère quel fichier :

Extension Lecteur
.csv read.csv(path)
.txt (séparé par tabulations) read.csv(path, sep = "\t")
.xlsx / .xls readxl::read_excel(path)
.rds readRDS(path)

Protéger avant qu’un fichier soit choisi

Au démarrage — et à tout moment avant que l’utilisateur ne téléverse — input$file vaut NULL. Appeler read.csv(NULL$datapath) ou l’indexer génère une erreur, et l’erreur surgit dans chaque sortie qui lit le reactive. req(input$file) arrête cela : il vérifie que la valeur est présente et, si non, arrête silencieusement le reactive pour que les sorties attendent simplement.

uploaded <- reactive({
  req(input$file)                  # do nothing until a file is uploaded
  read.csv(input$file$datapath)
})

Placez req(input$file) en haut du reactive, avant de toucher à datapath. Tant qu’aucun fichier n’arrive, uploaded() ne s’exécute pas et la table et le résumé restent vides au lieu d’afficher une erreur rouge. C’est le même req() que vous utilisez pour protéger n’importe quel pipeline piloté par les entrées (voir traitement des données).

Fichiers multiples

Réglez multiple = TRUE et l’utilisateur peut sélectionner plusieurs fichiers à la fois. input$file est toujours un data frame — désormais avec une ligne par fichier, donc input$file$datapath est un vecteur de chemins. Bouclez dessus avec lapply() et combinez les résultats.

ui <- fluidPage(
  fileInput("file", "Choose CSV files", accept = ".csv", multiple = TRUE),
  tableOutput("combined")
)

server <- function(input, output, session) {
  uploaded <- reactive({
    req(input$file)
    # read every uploaded file, then stack them into one data frame
    frames <- lapply(input$file$datapath, read.csv)
    do.call(rbind, frames)
  })

  output$combined <- renderTable({ head(uploaded()) })
}

lapply(input$file$datapath, read.csv) lit chaque chemin dans une liste de data frames ; do.call(rbind, ...) les empile (il suppose que les fichiers partagent les mêmes colonnes — combinez sur des en-têtes concordants). La forme est la même qu’un téléversement unique, simplement itérée : input$file est toujours un data frame, donc le cas multi-fichiers est une ligne ou plusieurs sans changer la façon dont vous lisez chaque datapath.

Limites de taille et types acceptés

Shiny plafonne les téléversements à 5 Mo par défaut ; un fichier plus gros échoue avec une erreur « maximum upload size exceeded ». Relevez le plafond avec options(shiny.maxRequestSize = ...), fixé en octets — placez-le en haut de app.R, en dehors de la fonction server, pour qu’il s’applique à toute l’application.

# at the top of app.R, before ui/server
options(shiny.maxRequestSize = 30 * 1024^2)   # 30 MB (30 * 1024 * 1024 bytes)

1024^2 est un mégaoctet en octets, donc 30 * 1024^2 fait 30 Mo. Utilisez l’argument accept de fileInput() pour orienter les utilisateurs vers les bons types de fichiers dans le sélecteur — accept = c(".csv", ".xlsx"). Traitez les deux comme une commodité et une première ligne de défense, pas comme une validation : accept est une indication d’interface que le navigateur peut ignorer, alors confirmez quand même l’extension avec tools::file_ext() côté server avant de lire.

Problèmes fréquents

input$file vaut NULL, donc l’application génère une erreur au démarrage. Avant que l’utilisateur ne téléverse quoi que ce soit, input$file n’a pas de valeur, et read.csv(input$file$datapath) (ou tout index dedans) lève une erreur — l’erreur s’affiche dans chaque sortie qui lit le reactive. Placez req(input$file) en haut du reactive pour qu’il attende sans bruit jusqu’à ce qu’un fichier soit réellement choisi.

Lire depuis le name d’origine au lieu de datapath. input$file$name est le nom de fichier sur la machine de l’utilisateur — le server ne peut pas l’ouvrir. read.csv(input$file$name) échoue avec « cannot open the connection ». Lisez toujours depuis input$file$datapath, le chemin temporaire où Shiny a enregistré le téléversement ; utilisez name seulement pour afficher le nom de fichier ou lire son extension avec tools::file_ext().

Un gros fichier échoue avec « maximum upload size exceeded ». Le plafond par défaut est de 5 Mo. Relevez-le avec options(shiny.maxRequestSize = 30 * 1024^2) (en octets) en haut de app.R, en dehors de la fonction server. Le régler à l’intérieur du server — ou l’oublier complètement — laisse le défaut en vigueur et les gros téléversements continuent d’échouer.

Questions fréquentes

Ajoutez fileInput("file", "Choose a file") au ui, puis lisez-le sur le server. Quand l’utilisateur choisit un fichier, input$file devient un data frame avec les colonnes name, size, type et datapath. Lisez le fichier depuis input$file$datapath — le chemin temporaire où Shiny a enregistré le téléversement — en protégeant d’abord avec req(input$file).

Lisez-le depuis le datapath du téléversement : read.csv(input$file$datapath) à l’intérieur d’un reactive(). Protégez avec req(input$file) en haut pour qu’il attende un téléversement, puis chaque sortie lit les données analysées avec uploaded(). Lisez depuis input$file$datapath, jamais depuis input$file$name (le nom d’origine pointe vers un fichier que le server ne peut pas voir).

C’est le chemin temporaire sur le server où Shiny a enregistré le fichier téléversé. input$file est un data frame qui décrit le téléversement — name (nom de fichier d’origine), size (octets), type (type MIME) et datapath — et datapath est celui que vous ouvrez avec read.csv() ou readxl::read_excel(). Le name d’origine réside sur la machine de l’utilisateur, vous ne pouvez donc pas le lire.

Utilisez le readxl package : readxl::read_excel(input$file$datapath) à l’intérieur d’un reactive(). C’est le même motif de téléversement que pour CSV — seul le lecteur change — et il lit la première feuille par défaut (sheet = pour en choisir une autre). Réglez accept = c(".xlsx", ".xls") sur fileInput() pour que le sélecteur propose les fichiers Excel.

Ajoutez multiple = TRUE à fileInput(). input$file a alors une ligne par fichier, donc input$file$datapath est un vecteur de chemins. Lisez-les tous avec lapply(input$file$datapath, read.csv) et combinez avec do.call(rbind, ...) quand les fichiers partagent les colonnes.

Le plafond par défaut est de 5 Mo. Relevez-le avec options(shiny.maxRequestSize = 30 * 1024^2) pour 30 Mo, placé en haut de app.R en dehors de la fonction server pour qu’il s’applique à toute l’application. La valeur est en octets, donc 30 * 1024^2 fait 30 mégaoctets.

Testez vos connaissances

Construisez une petite application avec un fileInput("file", "Upload a CSV", accept = ".csv") et deux sorties : une table qui affiche les premières lignes des données téléversées, et un texte qui indique combien de lignes a le fichier. Avant qu’un fichier soit choisi, aucune des deux sorties ne doit générer d’erreur.

Lisez le fichier une seule fois dans un reactive() : req(input$file) d’abord, puis read.csv(input$file$datapath). Appelez ce reactive depuis renderTable({ head(uploaded()) }) et renderText({ paste(nrow(uploaded()), "rows") }). La protection req() gère le cas sans fichier pour les deux sorties.

library(shiny)

ui <- fluidPage(
  fileInput("file", "Upload a CSV", accept = ".csv"),
  tableOutput("preview"),
  textOutput("rows")
)

server <- function(input, output, session) {

  uploaded <- reactive({
    req(input$file)                          # wait for an upload
    read.csv(input$file$datapath)            # read from datapath, not name
  })

  output$preview <- renderTable({ head(uploaded()) })
  output$rows    <- renderText({ paste(nrow(uploaded()), "rows") })
}

shinyApp(ui, server)

req(input$file) garde les deux sorties vides jusqu’à ce qu’un fichier soit téléversé ; read.csv(input$file$datapath) lit le fichier temporaire que Shiny a enregistré ; et le lire dans un seul reactive signifie que l’aperçu et le compteur partagent un seul parsing au lieu d’ouvrir le fichier deux fois.

Un utilisateur téléverse sales.csv vers votre fileInput("file", ...). Quelle expression lit correctement le fichier sur le server ?

A. read.csv(input$file) B. read.csv(input$file$name) C. read.csv(input$file$datapath) D. read.csv("sales.csv")

C. input$file est un data frame qui décrit le téléversement, et input$file$datapath est le chemin temporaire où Shiny a enregistré le fichier — c’est ce que vous lisez. A passe le data frame entier, pas un chemin ; B lit le name d’origine, qui pointe vers un fichier sur la machine de l’utilisateur que le server ne peut pas ouvrir ; D code en dur un nom auquel le server n’a aucun accès.

Conclusion

Un contrôle fileInput() est ce qui transforme une application Shiny d’un visualiseur de vos données en un outil pour celles de l’utilisateur. Le workflow est court une fois que le fait clé est compris : le server reçoit un data frame — name, size, type, datapath — et vous lisez le fichier depuis input$file$datapath, jamais le name d’origine. Enveloppez la lecture dans un reactive() protégé par req(input$file) pour qu’il attende un téléversement et que chaque sortie partage un seul parsing ; choisissez le lecteur selon l’extension avec tools::file_ext() ; bouclez sur input$file$datapath quand multiple = TRUE ; et relevez options(shiny.maxRequestSize) pour les gros fichiers. Alimentez le résultat directement dans une table ou un graphique et les données de l’utilisateur circulent dans le reste de votre application.

Ensuite, vous réunirez la table, les graphiques et les téléversements dans une mise en page de tableau de bord complète.

Leçons connexes

Cette page vous a-t-elle été utile ?

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Téléversement de fichier Shiny : lire un CSV téléversé avec
    fileInput en R},
  date = {2026-06-28},
  url = {https://www.datanovia.com/learn/programming/shiny/interactivity/file-uploads},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Téléversement de fichier Shiny : lire un CSV téléversé avec fileInput en R.” 2026. June 28. https://www.datanovia.com/learn/programming/shiny/interactivity/file-uploads.