R shiny save a file path for next session - r

I've been making an app in shiny, and it is meant to use/edit the same file for multiple different people.
The idea is that when you open the app for the first time, it'll prompt you to select the file, and save the location of the file so you don't have to select it every time you open the program.
I can't seem to find a way to do this, only saving edits to the file. Is there a way, or would you just have to select the file every time?
EDIT: here is some simple code to give you an idea of what i've been working with
library(shiny)
setwd("~/myfiles")
ui <- fluidPage(
fileInput("user_file", "Please enter a file"),
textOutput("txt_param")
)
server <- function(input, output, session) {
file_path <- input$user_file$datapath
output$txt_param <- renderText(as.character(input$user_file$datapath))
### Store the file's path in a csv to access later ###
as.data.frame(file_path)
write.csv(file_path, "user_file_path.csv")
}
shinyApp(ui, server)

Related

Shiny - How to test fileInput()

I'm trying to write tests in order to check if a shiny function fileInput() is reading files correctly.
My problem is that I don't know what to write in session$setInputs() in order to grab the file from my system.
Here is an example app:
library(shiny)
ui <- fluidPage(
tagList(
fileInput("file", "Please upload a file"),
tableOutput("text")
)
)
server <- function(input, output, session){
file <- reactive({input$file})
output$text <- renderTable({
req(file())
read.csv(file()$datapath)
})
}
shinyApp(ui, server)
Now, I want to be able to use testServer() in order to set a file address and see if my app loads it correctly, but I can't figure out how to do it:
address <- "path/to/text.csv"
testServer(server, {
session$setInputs(file = address)
print(file())
})
I think it has to do with the fact that fileInput() uploads the file to a temp folder and returns to shiny a dataframe where you can get the datapath, but I'm unable to simulate this pass in order to make the test work
I have the same question as you do, I did some investigating and could not find any way of testing fileInput with testServer or testthat. The best solution that I found was testing fileInput by taking a snapshot when recording a test with recordTest() of the shinytest package.
Sorry for answering this late.
I asked the same question at rstudio's forums and got an answer here
The basics of it are setting the file's datapath as a list:
address <- "path/to/text.csv"
testServer(server, { session$setInputs(file= list(datapath = address)) })

How can I store and retrieve files uploaded with fileInput after resetting it Shiny

I would like to create a storage to store and retrieve uploaded files even after fileInput is reset.
Basically every time user uploads a file with fileInput, in the future he is forced to click on doneUpload button which resets the fileInput text area and puts his file in the storage (no alternatives please).
At this point, user can go back and upload another file which will be put in the storage too.
From my point of view, I have all uploaded files which I can easily retrieve and manipulate.
In other words, my question could be translated to:
how can I reset fileInput text area without resetting uploaded files?
I have tried creating a reactive value to store uploaded files, however it does not work as I expected.
Here I show you an example to simplify my situation.
library(shiny)
ui<-fluidPage(
uiOutput("uploadFile"),
actionButton("doneUpload","Done"),
tableOutput("exampleTest"))
server<-function(input, output){
output$uploadFile<-renderUI({
fileInput("uploadFile", "Upload your file", accept = c(".csv"),placeholder="No files selected")
})
observeEvent(input$doneUpload,{
output$uploadFile<-renderUI({
fileInput("uploadFile", "Upload your file", accept = c(".csv"),placeholder="No files selected")
})
})
reactiveFileUploaded<-reactiveValues(fileUploaded=NULL)
observe({
req(input$uploadFile)
reactiveFileUploaded$fileUploaded<-c(reactiveFileUploaded$fileUploaded,input$uploadFile$datapath)
})
#Test to verify if the storage has been created.
#Supposing two files have been uploaded, I retrieve the first one.
output$exampleTest<-renderTable({
read.csv2(reactiveFileUploaded$fileUploaded[1])
})
}
shinyApp(ui=ui,server=server)
Here is a much simpler approach for what you need - Just set multiple = TRUE in fileInput() so that it can accept multiple files at the same time. They can all be read and stored in a reactive in one go using lapply.
library(shiny)
ui <- fluidPage(
fileInput("files", "Upload", multiple = TRUE),
actionButton("done", "Done Upload"),
verbatimTextOutput("test")
)
server <- function(input, output) {
all_data <- eventReactive(input$done, { # stores data in all files as a list of dataframes
req(input$files)
setNames(lapply(input$files$datapath, read.csv), sapply(input$files$name, basename))
})
output$test <- renderPrint({
# all_data()[[1]] # access first file; others can be accessed the same way
lapply(all_data(), head) # shows first 6 rows of all files with their names
})
}
shinyApp(ui, server)
Quite Simple, just read the file before clearing the input, after the User has confirmed the Input.
Currently you are reading (and saving) the file the moment the User has selected it, no matter if he wants to upload it or not. Also it seems like you are somehow triggering a loop after selecting a file constantly adding the file to the reactive value.
Also with the datapath you are saving only the filepath not the filecontent, and the filepath also directs to the temp folder so I would recommend changing that routine as well.
But for the most basic functionalities you described the following code should get the job done. (I also added a simple check for content in the filesUploaded variable, so that the error message doesn't appear on start up)
library(shiny)
ui<-fluidPage(
uiOutput("uploadFile"),
actionButton("doneUpload","Done"),
tableOutput("exampleTest"))
server<-function(input, output){
output$uploadFile<-renderUI({
fileInput("uploadFile", "Upload your file", accept = c(".csv"),placeholder="No files selected")
})
reactiveFileUploaded<-reactiveValues(fileUploaded=c())
observeEvent(input$doneUpload,{
req(input$uploadFile)
reactiveFileUploaded$fileUploaded<-c(reactiveFileUploaded$fileUploaded ,input$uploadFile$datapath)
output$uploadFile<-renderUI({
fileInput("uploadFile", "Upload your file", accept = c(".csv"),placeholder="No files selected")
})
})
#Test to verify if the storage has been created.
#Supposing two files have been uploaded, I retrieve the first one.
output$exampleTest<-renderTable({
if(length(reactiveFileUploaded$fileUploaded)>1)
read.csv2(reactiveFileUploaded$fileUploaded[1])
})
}
shinyApp(ui=ui,server=server)

Avoid Overwriting in file.copy in R

Can I avoid overwriting in case of file.copy() in Shiny in R. I know how to save file in a particular folder. But my code is overwriting uploaded file every case. I want that copied file should be saved with different sames. Can I do this in R? If yes, then how? I am posting my code. But my effort is just uploading files with same name i.e. "0.png". Please suggest the way of uploading files with different names. Thank you
server <- function(input, output) {
observeEvent (input$uploaded_file, {
file.copy(input$uploaded_file$datapath, "www")
})
}
ui <- fluidPage(
fileInput("uploaded_file", "Upload", multiple = FALSE)
)
shinyApp(ui = ui, server = server)

R Shiny select files from server-side directory

I have a folder called logs filled with different .csv files, formatted as telemetryLog-2017.21.08.54.11.csv (with varying dates and times at end).
For example, the above file could be stored like this: file <- read.csv("logs/telemetryLog-1969.2017.21.08.54.11.csv", header=TRUE)
The log files would be uploaded (in the logs folder, to shinyapps.io) along with the ui.R and server.R files. I would like to be able to obtain a list of the filenames in order to be able to select a file to display as data in a plot via selectInput (or any other way to list the files). The amount of files in the folder will not be an excessive amount; most likely it will be limited to around 50.
I have read the documentation for shinyFiles and to be completely honest I do not fully understand how the commands such as fileGetter or dirGetter work. Any help would be appreciated.
Instead of having people browse the file system of your server, you could also use list.files and specify the right directory there:
library(shiny)
ui <- fluidPage(
selectInput('selectfile','Select File',choice = list.files('log/')),
textOutput('fileselected')
)
server <- function(input,output)
{
output$fileselected <- renderText({
paste0('You have selected: ', input$selectfile)
})
}
shinyApp(ui,server)
Hope this helps!

server.R needs to be touched for execution

My Shiny app is supposed to read a directory and capture all rds files. It is running fine. But when a new rds file is coming into directory from where app suppose to read, it's not able to read new file. When I touch server.R then app is able to capture new file as well.
So long story in short, whenever a new file is coming into directory, I need to to touch server.R file to work as latest content. I am not making any changes in server.R. To execute successfully I need to run "touch server.R". has someone seen this before?
I am not able to understand, server.R needs any change in time stamp to run successfully.
Thanks!
Tinku
# MrFlick - No I haven't hard coded anything in server.R file. Actually same code is working on other server. I just copied the same program from test to qa box and not it changed the behavior. If I touched the server.R file and refresh the browser then it is working fine. Very starange for me!
#jdharrison - Thanks for your suggestion. But this (my existing server.R) code is running fine on dev server but when I moved to QA, then it not running as expected. I am surprised, that what touch or any non significant change in server.R is enabling it to run fine for one time.
Actually server.R code is reading the .RDS files from the directory and displaying in drop down list. it is working fine on dev server. But on QA server, if I am deleting or creating any new .RDS file then it's not displaying in drop down list automatically, until I touch the server.R file.
You can use a reactivePollto periodically check the directory you are interested in. In this example an actionButton allows the user to add a file to a test directory. The test directory is polled every second by the app and a table with file info is displayed:
library(shiny)
dir.create('test', showWarnings = FALSE)
write(1:3, 'test/dumfile.txt')
write(1:3, 'test/dumfile2.txt')
readTimestamp <- function() Sys.time()
valueFunc <- function() {
print(readTimestamp())
out <- lapply(list.files('test', full.names = TRUE), file.info)
do.call(rbind.data.frame, out)
}
runApp(list(
ui = bootstrapPage(
actionButton("addFile", "Add a file!"),
tableOutput('myTable')
),
server = function(input, output, session) {
observe({
if(input$addFile > 0){
write(1:3, tempfile('file', 'test', '.txt'))
}
})
dirData <- reactivePoll(1000, session, readTimestamp, valueFunc)
output$myTable <- renderTable({
myData <- dirData()
myData
})
}
))

Resources