I am trying to create a download handler in shiny, but using future_promise() because it is possible that writing the file could take some time. Here is a working example of what I'd like to do, but without using the async framework:
A working .Rmd shiny app: when you click on the button, it writes 10 random deviates to a file and offers it as a download. I added a delay of 5 seconds.
---
title: "download, no futures"
runtime: shiny
output: html_document
---
```{r setup, include=FALSE}
library(dplyr)
knitr::opts_chunk$set(echo = FALSE)
```
This version works.
```{r}
renderUI({
button_reactive <- reactive({
y = rnorm(10)
Sys.sleep(5)
tf = tempfile(fileext = ".txt")
cat(c(y,'\n'), sep='\n', file = tf)
d = readBin(con = tf, what = "raw", n = file.size(tf))
return(list(fn = basename(tf), d = d))
})
output$button <- downloadHandler(
filename = function() {
button_reactive() %>%
`[[`('fn')
},
content = function(f) {
d = button_reactive() %>%
`[[`('d')
con = file(description = f, open = "wb")
writeBin(object = d, con = con)
close(con)
}
)
shiny::downloadButton(outputId = "button", label="Download")
})
I'm trying to implement this in the async framework using future_promise. Here's the {future}/{promises} version:
---
title: "download futures"
runtime: shiny
output: html_document
---
```{r setup, include=FALSE}
library(future)
library(promises)
plan(multisession)
library(dplyr)
knitr::opts_chunk$set(echo = FALSE)
```
This version yields this error on download attempt, reported in the R console:
```
Warning: Error in enc2utf8: argument is not a character vector
[No stack trace available]
```
```{r}
renderUI({
button_reactive <- reactive({
future_promise({
y = rnorm(10)
Sys.sleep(5)
tf = tempfile(fileext = ".txt")
cat(c(y,'\n'), sep='\n', file = tf)
d = readBin(con = tf, what = "raw", n = file.size(tf))
return(list(fn = basename(tf), d = d))
}, seed = TRUE)
})
output$button <- downloadHandler(
filename = function() {
button_reactive() %...>%
`[[`('fn')
},
content = function(f) {
con = file(description = f, open = "wb")
d = button_reactive() %...>%
`[[`('d') %...>%
writeBin(object = ., con = con)
close(con)
}
)
shiny::downloadButton(outputId = "button", label="Download")
})
When I click the button in Firefox, I get no file and in the R console, this is shown:
Warning: Error in enc2utf8: argument is not a character vector
[No stack trace available]
After some debugging, I believe this occurs because whatever is running the download handler is running the filename
function, expecting a character vector, and getting a promise. But I'm not sure how to fix this.
I saw this question, in which the asker seems to have the same problem, but no solution was offered (and their example was not reproducible).
How can I fix this?