0

このリンクで説明されているように、WS を使用してファイルをダウンロードするための単純な iteratee を作成しました。

次のスニペットを検討してください。

import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import org.specs2.mutable.Specification
import org.specs2.time.NoTimeConversions
import play.api.libs.Files.TemporaryFile
import play.api.libs.iteratee.{Done, Input, Cont, Iteratee}
import play.api.libs.ws.WS
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

class DummySpec extends Specification with NoTimeConversions {
  def fileChannelIteratee(channel: FileChannel): Iteratee[Array[Byte], Unit] = Cont {
    case Input.EOF =>
      println("Input.EOF")
      channel.close()
      Done(Unit, Input.EOF)
    case Input.El(bytes) =>
      println("Input.El")
      val buf = ByteBuffer.wrap(bytes)
      channel.write(buf)
      fileChannelIteratee(channel)
    case Input.Empty =>
      println("Input.Empty")
      fileChannelIteratee(channel)
  }

  "fileChannelIteratee" should {
    "work" in {
      val file = TemporaryFile.apply("test").file
      val channel = FileChannel.open(file.toPath)

      val future = WS.url("http://www.example.com").get(_ => fileChannelIteratee(channel)).map(_.run)

      Await.result(future, 10.seconds)

      file.length !== 0
    }
  }
}

iteratee が Input.EOF を受け取っていないように見えるため、WS.get の後に .map(_.run) を呼び出しても、ここでは効果がないようです。チャンネルを閉じることができなくなります。これは私が得る出力です:

Input.El
[info] DummySpec
[info]
[info] fileChannelIteratee should
[info] x work (941 ms)
[error]    '0' is equal to '0' (DummySpec.scala:37)
[info]
[info]
[info] Total for specification DummySpec
[info] Finished in 948 ms
[info] 1 example, 1 failure, 0 error

私は何を間違っていますか?

Play Framework 2.2.2 を使用しています。

前もって感謝します。

4

1 に答える 1

0

FileChannel を間違った方法で開いていました。パラメータが指定されていない場合、このリンクによると、デフォルトで読み取りモードになるようです。

からスローされた例外は、操作全体の戻り値の型が であるため、操作channel.writeによって飲み込まれていました。この場合、内部が失敗しても、外部は成功した状態です。代わりに使用する必要があります。mapFuture[Future[Unit]]FutureflatMap

于 2014-03-26T14:44:09.950 に答える