Потоковое динамическое содержимое с помощью 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, является противоположным, потому что субъект потоковой передачи должен извлекать данные, когда они будут готовы - я не могу просто отправить все данные в поток.

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

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 автоматически выдаст фрагментарный ответ.

Другие вопросы по тегам