Scala 使用分块传输文件下载进行内容处置

Scala 使用分块传输文件下载进行内容处置,scala,download,akka,spray,content-disposition,Scala,Download,Akka,Spray,Content Disposition,我有一个在Jetty上运行的Spray应用程序,它向客户端发送PDF。分块发送文件很方便,因为它可能会变得非常大 问题在于,尽管设置了内容配置和媒体类型字段,但文件在浏览器中呈现,而不是下载 责任参与者的recieve()方法: val chunkIterator: Iterator[HttpData] = httpData.iterator def receive = { case FirstChunk if chunkIterator.hasNext =>

我有一个在Jetty上运行的Spray应用程序,它向客户端发送PDF。分块发送文件很方便,因为它可能会变得非常大

问题在于,尽管设置了
内容配置
媒体类型
字段,但文件在浏览器中呈现,而不是下载

责任参与者的
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
关于如何强制下载该文件的任何线索

使用
MetaMarshaller.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[将数据转换为
流[T]
]时的编译问题,但仍然存在相同的问题,文件下载选项没有显示,而是在浏览器中呈现为文本。在各种操作系统上使用各种浏览器进行测试

是否有任何理由不返回
流[T]
使用spray?我几乎一字不差地将您的
starterResponse
复制到最新spray源代码的on spray can和on jetty示例中,在那里它绝对有效。在过去,一些浏览器(即…)在解释
内容配置时遇到一些问题,因此可能是浏览器问题?@jrudolph这可能是由于缺少明确的
封送器造成的吗?我有一个简单的函数,可以将生成的PDF流转换为
HttpData
private def arrayToHttpData(data:bytearrayoutpstream)={Iterable(data.toByteArray.map(HttpData.apply)}
@jrudolph:我在Linux上使用最新版本的Chrome/Firefox进行测试(晚了一年),谢谢@jrudolph。这确实是一个浏览器问题。