@jdharrison 的回答是您GET
在 Shiny 中处理请求的一种方式。不幸的是,他或她的声明
不幸的是,闪亮不处理 POST 请求。
严格来说,不是 100% 准确的。
您可以POST
借助函数在 Shiny中处理请求session$registerDataObj
。在这个例子中可以找到一个使用这个函数的例子。基本上,通过调用registerDataObj
函数,它返回一个唯一的请求 URL,您可以向该 URL 发起一个GET
或多个POST
请求。但是,对于您的问题,我认为上面的示例不会很有帮助,因为:
- 此示例中没有明确使用 AJAX。相反,该示例利用
registerDataObj
创建一个 PNG 文件处理程序,并将 URL 直接绑定到tag的src
属性。<img>
- 它仍在使用
GET
request not POST
。
但是,您可以多路复用这个方便的功能来处理这两者GET
并且POST
非常好。考虑以下示例:
服务器.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))
})
用户界面
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 type="text" name="name" /> <br />
<span>Passcode: </span> <br />
<input type="password" name="passcode" /><br />
<span>Avatar:</span>
<input name="file" type="file" /> <br />
<input type="button" value="Upload" id="submitbtn" />
</form>
')
)
)
))
现在,假设我输入这些测试输入:

然后点击"Upload"
,您向 Shiny 服务器提交一个 POST 请求,该服务器基于我们的 R 代码,会将您的浏览器的 POST 请求流作为响应转储给您。
例如,我得到:
------WebKitFormBoundary5Z0hAYXQXBHPTLHs
Content-Disposition: form-data; name="name"
foo
------WebKitFormBoundary5Z0hAYXQXBHPTLHs
Content-Disposition: form-data; name="passcode"
bar
------WebKitFormBoundary5Z0hAYXQXBHPTLHs
Content-Disposition: form-data; name="file"; filename="conductor.png"
Content-Type: image/png
‰PNG
IHDR X ¦ 5Š_ pHYs a a¨?§i ÕiTXtXML:com.adobe.xmp <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.1.2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
<tiff:Compression>5</tiff:Compression>
<tiff:PhotometricInterpretation>2</tiff:PhotometricInterpretation>
<tiff:Orientation>1</tiff:Orientation>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
# here I removed the binary file content
------WebKitFormBoundary5Z0hAYXQXBHPTLHs--
显然,只要您适当地编写 POST 请求处理器,您不仅可以处理文本数据,还可以处理文件上传。虽然这可能不是微不足道的,但至少它是合理的,完全可行的!
当然,您有一个明显的缺点,即您需要以某种方式将此唯一的请求 URL 传递给客户端,或者传递给将启动请求的服务器。但从技术上讲,有很多方法可以做到这一点!