似乎无法使用body> 10K
进行POST如果我这样做:
WS.url(url).post("content more than 10K")
我的身体被剪掉了。正好10K。 我该如何避免这种限制?
答案 0 :(得分:0)
通常的方法是通过流POST(或PUT)大型文档。这曾经比它应该更难,但如果你愿意使用Play 2.3它已经有所改进。查看What's new?页面上的“播放WS”部分。底层的AsyncHttpClient可能就是你所需要的 - Play用来不让你知道它,甚至现在你需要在将对象拉出WS之后使用另一个库(Dispatch)。
基本上,如上面的文档所示,您实例化一个NingWSClient,使用.underlying
拉出AsyncHttpClient,然后对其进行异步调用以发布您的流。这两个历史线程中的第二个为您提供了更多提示,但是弄清楚如何在AsyncHttpClient上进行相关调用本身会很有趣。我会看看今晚是否可以弄清楚,但我认为这对你现在可能有用。
Play WS (2.2.1): post/put large request - 接受的答案显示了如何获得底层HTTP客户端。第二个答案预示着上面的Play 2.3功能。
Simple and concise HTTP client library for Scala - 接受的答案是关于Dispatch,它是Ning的异步HTTP客户端的Scala包装器,这是第一个线程接受的答案所指的。
我必须说Dispatch doc值得称赞。除非有人为你的问题提出一个简单的解决方案,或者如果你需要大量发布大文档,我真的推荐2.3路由和Dispatch。
编辑:以下是一个如何在不使用WS API的情况下执行此操作的示例,但直接使用Ning客户端。我使用了Play 2.4.0-M1中play-ws库附带的Ning软件包,因为它是我方便的。您可以单独获取Ning库并坚持使用您正在使用的任何Play版本。这是根据a streaming GET example I found
改编的import scala.concurrent.Promise
import com.ning.http.client._
import com.ning.http.client.Response
import com.ning.http.client.AsyncCompletionHandler
import scala.concurrent.ExecutionContext.Implicits.global
import java.io.ByteArrayInputStream
object AsyncWS {
def main(args: Array[String]): Unit = {
val config = new AsyncHttpClientConfig.Builder()
val client = new AsyncHttpClient(config.build())
// this will send back your request including the body
val url = "http://httpbin.org/post"
// testing the basic approach by still reading from a string -- this
// should work if you can fir your text into a string, otherwise
// you'll need to write some stream magic
val testInputStream =
new ByteArrayInputStream("s short test string".getBytes)
val requestBuilder = client.preparePost(url)
requestBuilder.setBody(testInputStream)
val request = requestBuilder.build()
var result = Promise[Int]()
client.executeRequest(request, new AsyncCompletionHandler[Response]() {
override def onCompleted(response: Response) = {
println("got an answer")
val is = response.getResponseBodyAsStream()
val in = scala.io.Source.fromInputStream(is)
in.getLines().foreach(println(_))
in.close()
result.success(response.getStatusCode())
response
}
override def onThrowable(t: Throwable) {
result.failure(t)
}
})
val getFuture = result.future
getFuture.map { status =>
println("result status = " + status)
}.recover {
case e: Throwable => {
println("error e = " + e)
}
}
}
}