2

I have a shiny app that needs to be able to take a file in from the web / s3 / a pre-signed download url. I have a custom javascript widget that i am able to get a presigned url from or public s3 path. I am building off of this question / answer Accept HTTP Request in R shiny application

My current understanding is that I need to get this pre-signed url and post it to shiny server.

I have tried making my own input bindings, but my understanding is that fileInput is a bit different from other custom inputs and has it's own code codepath on the in the ui and server.

I think I need to access the underlying server side code here https://github.com/rstudio/shiny/blob/master/R/shiny.R#L1674 and below (handleRequest, saveFileUrl, etc.) but am unsure of the right way to do this.

My end goal is that this file will be available as an 'input'.

This is my current code (building off of the linked example) I can see the file posting to the server (I think..) and getting a 200 back--but am not sure what to do next.

server.R

library(shiny)

shinyServer(function(input, output, session) {
  api_url <- session$registerDataObj( 
    name   = 'api', # an arbitrary but unique name for the data object
    data   = list(), # you can bind some data here, which is the data argument for the
                     # filter function below.
    filter = function(data, req) {
      print(ls(req))  # you can inspect what variables are encapsulated in this req
                      # environment
      if (req$REQUEST_METHOD == "GET") {
        # handle GET requests
        query <- parseQueryString(req$QUERY_STRING)
        # say:
        # name <- query$name
        # etc...
      } 

      if (req$REQUEST_METHOD == "POST") {
        # handle POST requests here

        reqInput <- req$rook.input

        # read a chuck of size 2^16 bytes, should suffice for our test
        buf <- reqInput$read(2^16)

        # simply dump the HTTP request (input) stream back to client
        shiny:::httpResponse(
          200, 'text/plain', buf
        )
      }          
    }
  )

  # because the API entry is UNIQUE, we need to send it to the client
  # we can create a custom pipeline to convey this message
  session$sendCustomMessage("api_url", list(url=api_url))

})


ui.R

library(shiny)

shinyUI(fluidPage(
  singleton(tags$head(HTML(
    '
    <script type="text/javascript">
      $(document).ready(function() {
        // creates a handler for our special message type
        Shiny.addCustomMessageHandler("api_url", function(message) {
          // set up the the submit URL of the form
          $("#form1").attr("action", "/" + message.url);
          $("#submitbtn").click(function() { $("#form1").submit(); });
        });
      })
    </script>
  '
  ))),
  tabsetPanel(
    tabPanel('POST request example',
             # create a raw HTML form
             HTML('
                  <form enctype="multipart/form-data" method="post" action="" id="form1">
                      <span>Name:</span>
                      <input name="file" type="file" /> <br />
                  </form>
            ')
    )
  )
))
Alex
  • 152
  • 6

0 Answers0