Потоковая передача динамического контента с помощью Spray Route

Я разрабатываю веб-службу, которая обслуживает несколько относительно больших файлов, каждый из которых создается динамически во время запроса. В моем случае это ZIP-архив, содержащий кучу файлов, но я предполагаю, что та же проблема возникнет и с другими типами динамически создаваемых файлов.

Проблема в том, что я хотел бы не создавать ZIP-файл на диске, а просто передавать его прямо в ответ HTTP. Один из способов, о котором я думал, - это использовать потоковую передачу по частям, что означает, что потоковый актор отправляет порцию в то время и «ждет» подтверждения от респондента, прежде чем отправлять следующие порции. (см. пример sendStreamingResponse в https://github.com/spray/spray/blob/release/1.1/examples/spray-routing/on-spray-can/src/main/scala/spray/examples/DemoService.scala)

К сожалению, все примеры, которые я смог найти, показывают, как это сделать, когда ваш поток предопределен, но я не совсем уверен, как лучше всего подойти к этому, когда поток данных готовится в каком-то другом будущем.

В моем случае есть Future, запущенный HTTP-запросом, который выполняет всю тяжелую работу по извлечению файлов и записи их в java.util.zip.ZipOutputStream. Но потоковая передача в Spray работает наоборот, потому что потоковому актору нужно получить данные, когда они будут готовы — я не могу просто отправить все данные в поток.

Является ли это знакомым вариантом использования и как лучше всего с ним справиться?


person yby    schedule 11.11.2015    source источник


Ответы (1)


Я думаю, что мы можем использовать встроенный маршаллер Spray, если создадим файл Steam[Byte]. Я не пробовал, но что-то вроде этого должно работать (в прошлом я делал что-то подобное с динамическим изменением размера изображения и обслуживанием больших файлов).

val pipeIn = new PipedInputStream()
val pipeOut = new PipedOutputStream(pipeIn)
val out = new ByteArrayOutputStream()
val st = new ZipOutputStream(out)
Future{
  writeToZip(st)
  out.writeTo(pipeOut)
}
val streamResponse: Stream[Byte] = Stream.continually(pipeIn.read).takeWhile(_ != -1).map(_.toByte)
complete(streamResponse)

Упорядочивающий поток Spray автоматически создаст фрагментированный ответ.

person rahilb    schedule 12.11.2015