library(shiny)
library(plyr)
shinyServer(function(input, output){
myfile<-reactive({
#reading 3 csv files and merging them into a dataframe
})
output$downloadData<-downloadHandler(
filename = function(){
paste("mergedfile","csv",sep='.')
},
content= function(file){
write.csv(myfile(),file,sep=",")
}
)
})
I am reading 3-4 files reactively and then merging them. After that without displaying them I need to download the merged file.
I wrote the above code but a dialog box opens which asks me where to save but the file doesn't get saved. Am I doing something wrong with the download handler.
ui.R
downloadButton('downloadData','Download')
This is what I have in my main panel in ui.R file
Your probably using the Rstudio viewer to run the app? Open the app in your browser and your code will work
( click open in borwser or run runApp('/path/to/myApp',launch.browser=T) ).
See this link.
Also no need to set sep="," for write.csv since this is the default.
Related
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!
In my Shiny app, I run calculations, generate a data frame, and want the user to be able to save (download) it.
My relevant code in ui.R:
textInput("downFile","Save the File:", value = "Results File"),
downloadButton('downFile',"Save File"),
My relevant code in server.R:
output$downFile <- downloadHandler(
filename = function() {
paste0(input$downFile, " ", Sys.Date(), ".csv")
},
content = function(file) {
write.csv(MyMainFunction()$mydataframe, file, row.names = FALSE)
}
)
Everything works. But I have two issues:
If by mistake the user clicks on "Save File" before all the calculations in server.R have been completed, he gets an error ("Failed - Network Error").
After all the calculations, when the user clicks on the "Save File" button, the file is immediately saved in "Downloads" folder.
Two questions:
Is it possible to make the button invisible until the calculations in my main function (MainFunction) are completed?
How could I allow the user to select a desired folder to download the results to? (as in "Save in...")
Thank you very much!
for question 1: Use shinyjs package learn more in https://deanattali.com/shinyjs/
library(shinyjs)
disable("downFile") # or use hide() Before all calculations
enable("downFile") # or use show() After
For question 2: I think this is more about setting up your browser than the shiny
If you are using chrome go to the advanced settings and enable
I have a very large fixed width file I need to read in using my Shiny application. The way my program is currently structured is the ui.R contains a fileInput allowing the user to locate the file using the browser.
On the server side, I only capture the path to the file such as the following:
path2file <- reactive({
infile <- input$path2file
if (is.null(infile)) return(NULL)
infile$datapath
})
A subsequent function takes that path as input and the proceeds to read in the file according to its layout specifications. This all works just fine; however when dealing with extremely large fwf files my program slows down tremendously and takes hours to get the path name of the file read in using fileInput
My suspicion is that fileInput is actually reading in the entire file and then my function only returns the datapath even though I am not explicitly reading in any file format type within the function.
My aim is to continue using the program as I have it structured now and obtain only the path to this file using my fileInput. I have found this topic on SO, and see it is a possible option.
Getting file path from Shiny UI (Not just directory) using browse button without uploading the file
However, I also aim to minimize the number of package dependencies I have; this has become a big issue and so if I MUST use an additional package I will, but I'd like to avoid that at all costs.
I experimented with this cheap trick:
path2file <- reactive({
infile <- input$path2file
if (is.null(infile)) return(NULL)
scan(infile$datapath, n = 1)
infile$datapath
})
Thinking that it would be a fast workaround, but it too is extremely slow so I suspect it too is not reading in only n = 1. So, my question is can anyone identify a way to use fileInput to allow a user to locate a file and have the server side function capture only the path and NOT read in the file or try and parse it in any way? More importantly, can this be done using functions in base R and Shiny alone without having to grab functions from other extended packages?
The above is the relevant portion of code in the server.R file and the relevant portion of code in the ui.R file is
fileInput('path2dor', 'Choose the DOR .txt file to format',
accept=c('text/csv',
'text/comma-separated-values,text/plain', '.csv')),
Thank you for you advice.
This functionality is not possible with fileInput. The reason is because 'fileInput' do not provide local path information to the server for security reasons.
With fileInput the user navigates through the browser on his local machine, the resulting file on the server side is the uploaded copy of the selected local once.
As an alternative you can use the shinyFiles package, which do navigate through the server side. This means, that you get all the paths on your local machine.
A second alternative could be a simple text input, which lets the user add a path by hand (make sure to check the path on the server side to not run into any troubles).
As pointed by others, due to security concerns shiny creates a tmp folder with all files loaded called with fileinput
Accordingly, you need to select all the files of interest in your folder and then call this tmp file with ...$datapath
Note however that each element of datapath will include both the directory information and the corresponding file name. Accordingly, you need to trim those paths to only account for the tmp directory. This can be achieved as follows...
Assume you will create an object called phu which will only contain the first file in the folder (using input$upload$datapath[1]) you called with fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE)
phu<-as.character(input$upload$datapath[1])
phu<-substr(phu,1,nchar(phu)-5)
The second line removes the last five characters in the string. These characters are 0.txt or whatever other extension you called in your input. The code provided only works with .txt files and requires the tm package. You can now use the object phu as the input directory of interest.
Finally, you need to call this output with an output object and print it in your ui this is shown with textOutput("Pdiretory") below.
The following example shows the entire process. Note that there are no security concerns because this temporary file and its content will be deleted at closing. Once more, the input files are .txt files.
library(shiny)
library(tm)
ui <- fluidPage(
fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE),
textOutput("Pdiretory")
)
server <- function(input, output, session) {
listdir <- eventReactive(input$upload, {
phu<-as.character(input$upload$datapath[1])
phu<-substr(phu,1,nchar(phu)-5)
txt<-Corpus(DirSource(phu),readerControl = list(language = "en"))
print(txt)
})
output$Pdiretory <- renderPrint ({
listdir()
})
}
shinyApp(ui = ui, server = server)
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
})
}
))
I am playing around with RShiny recently, and I've built a working web interface that takes two parameters "date" and "location" and gives me back a series of graphs and tables from our database that fit the criteria.
What I would like to do with that, is to have users being able to download all the data and graphs in the form of a RMD report in HTML format.
so I have
1. UI.R with a download button
2. Server.R's downloadHandler starts my RMD script
3. ????
UI.R
downloadButton('downloadData','Download')
Server.R
output$downloadData<- downloadHandler(filename ="myData.html",
content= function(file= NULL){
knit(thread.RMD)
}
Here is the answer I got from the Shiny Google Group : https://groups.google.com/forum/?fromgroups=#!topic/shiny-discuss/XmW9V014EtI
The function that's given as the 'content' argument to downloadHandler takes one option, 'file'. When the download button is clicked, the download handler calls that function, and it uses the file argument to tell it where is should save the output file.
I don't see a way to set the output file name from knit2html(), but you can just rename it after it's created:
output$downloadData <- downloadHandler(
filename ="ShinyData.html",
content = function(file) {
knit2html("myreport.rmd")
file.rename("myreport.html", file)
}
)
(Also, you're missing a closing parenthesis in ui.r.)
-Winston