Scala 使用play framework 2.3动态下载归档文件

Scala 使用play framework 2.3动态下载归档文件,scala,zip,streaming,playframework-2.3,archive-file,Scala,Zip,Streaming,Playframework 2.3,Archive File,我正在尝试在不依赖内存的情况下创建和下载存档文件(以避免大文件出现内存不足异常),我正在使用Scala的play framework 2.3,经过一些研究后,我发现了一个示例:,我对其进行了一些修改。我的问题是,当我下载文件并尝试打开它时,会出现以下异常:加载存档文件时出错。 以下是所有代码: def zip() = Action { implicit request: Request[AnyContent] => val buffer = new ZipBuff

我正在尝试在不依赖内存的情况下创建和下载存档文件(以避免大文件出现内存不足异常),我正在使用Scala的play framework 2.3,经过一些研究后,我发现了一个示例:,我对其进行了一些修改。我的问题是,当我下载文件并尝试打开它时,会出现以下异常:加载存档文件时出错。 以下是所有代码:

 def zip() = Action {
      implicit request: Request[AnyContent] =>
      val buffer = new ZipBuffer(10000)

      val writeCentralDirectory = Enumerator.generateM(Future{
        if (buffer.isClosed) {
          None
        }
        else {
          buffer.flush
          buffer.close
          Some(buffer.bytes)
        }
      })

      val test = Enumerator.apply(ResolvedSource2("test.txt", "helllo"))    

      Ok.chunked(test &> zipeach2(buffer) andThen writeCentralDirectory >>> Enumerator.eof) as withCharset("application/zip") withHeaders(
        CONTENT_DISPOSITION -> s"attachment; filename=aa.zip")
  }
  case class ResolvedSource2(filepath: String, stream: String)
  def zipeach2(buffer: ZipBuffer)(implicit ec: ExecutionContext): Enumeratee[ResolvedSource2, Array[Byte]] = {
    Enumeratee.mapConcat[ResolvedSource2] { source =>
      buffer.zipStream.putNextEntry(new ZipEntry(source.filepath))
       var done = false
      def entryDone: Unit = {
        done = true
        buffer.zipStream.closeEntry
      }
      def restOfStream: Stream[Array[Byte]] = {
        if (done) Stream.empty
        else {
           while (!done && !buffer.full) {
          try {
            val byte = source.stream
            buffer.zipStream.write(byte.getBytes)
           entryDone
          }
          catch {
            case e: IOException =>
              println(s"reading/zipping stream [${source.filepath}]", e)
          }
           }
          buffer.bytes #:: restOfStream
        }
      }
      restOfStream
    }
  }
}

class ZipBuffer(capacity: Int) {
  private val buf = new ByteArrayOutputStream(capacity)
  private var closed = false
  val zipStream = new ZipOutputStream(buf)
  def close(): Unit = {

    if (!closed) {
      closed = true
      reset
      zipStream.finish()
      zipStream.close   // writes central directory
    }
  }
  def flush() = {
    zipStream.flush()
  }

  def isClosed = closed

  def reset: Unit = buf.reset

  def full: Boolean = buf.size >= capacity

  def bytes: Array[Byte] = {
    val result = buf.toByteArray
    reset
    result
  }
}