Итерация записи файла не получает EOF для WS.get

Я создал простую итерацию для загрузки файла с помощью WS, как описано в этой ссылке.

Рассмотрим следующий фрагмент:

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
    }
  }
}

Вызов .map(_.run) после WS.get, по-видимому, не имеет здесь никакого эффекта, поскольку итерируемый, похоже, не получает Input.EOF. Это мешает мне закрыть канал. Это результат, который я получаю:

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.

Заранее спасибо.


person Emre    schedule 26.03.2014    source источник


Ответы (1)


Я неправильно открывал FileChannel. Кажется, по умолчанию используется режим чтения в соответствии с эта ссылка, если параметры не заданы.

Исключение, созданное из channel.write, было проглочено операцией map, поскольку тип возвращаемого значения всей операции — Future[Future[Unit]]. Внешний Future находится в успешном состоянии, даже если в этом случае внутренний терпит неудачу. Вместо этого следует использовать flatMap.

person Emre    schedule 26.03.2014