我在Jetty上运行了一个Spray应用程序,它将PDF发送给客户端。以块的形式发送文件很方便,因为它可能会变得非常大。
问题是尽管设置了Content-Disposition
和Media-Type
字段,但文件在浏览器中呈现而不是下载。
负责人的recieve()
方法:
val chunkIterator: Iterator[HttpData] = httpData.iterator
def receive = {
case FirstChunk if chunkIterator.hasNext =>
val starterResponse = HttpResponse(headers = List(HttpHeaders
.`Content-Disposition`.apply("attachment", Map("filename" -> FILENAME)))
, entity = HttpEntity(MediaTypes.`application/pdf`, chunkIterator.next)
)
ctx.responder ! ChunkedResponseStart(starterResponse).withAck(ResponseAck)
case FirstChunk =>
ctx.responder ! ChunkedResponseStart(HttpResponse(entity = Empty))
context.stop(self)
case ResponseAck if chunkIterator.hasNext =>
val nextChunk = MessageChunk(chunkIterator.next)
ctx.responder ! nextChunk.withAck(ResponseAck)
case ResponseAck =>
ctx.responder ! ChunkedMessageEnd
context.stop(self)
case error => log.warning("connection closed due to {}", error)
}
从浏览器中看到的标题
Content-Disposition → attachment; filename=file.pdf
Content-Type → application/pdf
Date → Fri, 04 May 2015 09:13:57 GMT
Server → Jetty(9.2.10.v20150310)
Transfer-Encoding → chunked
有关如何强制下载文件的任何线索?
使用MetaMarshallers.streamMarshaller[T]
implicit val pdfStreamMarshaller = MetaMarshallers.streamMarshaller[Array[Byte]]
val route = {
path("api" / "pdfservice") {
post {
respondWithHeader(`Content-Disposition`("attachment", Map(("filename", "some.pdf")))) {
respondWithMediaType(MediaTypes.`application/pdf`) {
entity(as[Params]) {
params => {
ctx => {
onComplete(
getPdfStream(params)
){
case Success(value) => ctx.complete(value)
case Failure(ex) => ctx.complete(s"Oops, error encountered ${ex.getMessage}")
}
}
}
}
}
}
}
private def getStream(params: Params) :Future[Array[Byte]]
编辑:使用方法2 [将数据转换为Stream[T]
]修复了编译问题,但它仍然存在相同的问题,文件下载选项未显示,而是在浏览器中呈现为文本。在各种操作系统上使用各种浏览器进行测试。