1

图像在被检索(通过 HTTP)然后(通过 HTTP)发送到数据库时损坏。图像的原始数据以字符串形式处理。

该服务为图像文件发送 GET,接收带有原始图像数据(响应的正文)和 Content-Type 的响应。然后,使用上述请求的正文和 Content-Type 标头发送 PUT 请求。(PUT 请求是通过在 String 中提供正文来构造的)这个 PUT 请求被发送到一个 RESTful 数据库(CouchDB),创建一个附件(对于那些不熟悉 CouchDB 的人来说,附件就像一个静态文件)。

现在我有了原始图像,我的服务 GET 和 PUT 到数据库,以及原始图像的“副本”,我现在可以从数据库中获取。如果我然后 `curl --head -v "[copy's url]" 它具有原始图像的 Content-Type,但 Content-Length 已更改,从 200kb 变为约 400kb。如果我使用浏览器获取“复制”图像,则不会渲染它,而原始图像渲染得很好。它已损坏。

可能是什么原因?我的猜测是,在将原始数据作为字符串处理时,我的框架猜测编码错误并破坏了它。我无法确认或否认这一点。我怎样才能以安全的方式处理这个原始数据/请求主体,或者我怎样才能正确处理编码(如果这被证明是问题的话)?

详细信息:Play2 框架的 HTTP 客户端,Scala。下面是一个重现的测试:

"able to copy an image" in {
  def waitFor[T](future:Future[T]):T = { // to bypass futures
    Await.result(future, Duration(10000, "millis"))
  }
  val originalImageUrl = "http://laughingsquid.com/wp-content/uploads/grumpy-cat.jpg"
  val couchdbUrl = "http://admin:admin@localhost:5984/testdb"
  val getOriginal:ws.Response = waitFor(WS.url(originalImageUrl).get)
  getOriginal.status mustEqual 200
  val rawImage:String = getOriginal.body
  val originalContentType = getOriginal.header("Content-Type").get

  // need an empty doc to have something to attach the attachment to
  val emptyDocUrl = couchdbUrl + "/empty_doc"
  val putEmptyDoc:ws.Response = waitFor(WS.url(emptyDocUrl).put("{}"))
  putEmptyDoc.status mustEqual 201
  //uploading an attachment will require the doc's revision
  val emptyDocRev = (putEmptyDoc.json \ "rev").as[String]

  // create actual attachment/static file
  val attachmentUrl = emptyDocUrl + "/0"
  val putAttachment:ws.Response = waitFor(WS.url(attachmentUrl)
    .withHeaders(("If-Match", emptyDocRev), ("Content-Type", originalContentType))
    .put(rawImage))
  putAttachment.status mustEqual 201

  // retrieve attachment
  val getAttachment:ws.Response = waitFor(WS.url(attachmentUrl).get)
  getAttachment.status mustEqual 200
  val attachmentContentType = getAttachment.header("Content-Type").get

  originalContentType mustEqual attachmentContentType
  val originalAndCopyMatch = getOriginal.body == getAttachment.body
  originalAndCopyMatch aka "original matches copy" must beTrue // << false
}

最后“必须”失败:

[error] x  able to copy an image
[error]    original matches copy is false (ApplicationSpec.scala:112)
4

1 回答 1

1

转换String为肯定会引起问题。您需要使用 Daniel 提到的字节。

查看源代码,它看起来ws.Response只是一个包装器。如果你进入底层类,那么有一些方法可以帮助你。在 Java 方面,有人在 GitHub 上进行了提交,以公开获取响应数据的更多方式,而不是String.

我不熟悉scala,但这样的事情可能会奏效:

getOriginal.getAHCResponse.getResponseBodyAsBytes

// instead of getOriginal.body

WS.scala
https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/libs/ws/WS.scala

WS.java
在这里你可以看到Response有一些新的方法,getBodyAsStream()并且asByteArray.
https://github.com/playframework/playframework/blob/master/framework/src/play-java/src/main/java/play/libs/WS.java

于 2013-08-21T17:33:24.943 回答