Проблемы загрузки / выгрузки файлов в akka-http/akka-streams

Я пытаюсь использовать akka-streams, akka-http и библиотеку alpakka для загрузки / выгрузки файлов в Amazon S3. Я вижу две проблемы, которые могут быть связаны...

  • Я могу загружать только очень маленькие файлы, самый большой из которых 8 КБ.
  • Я не могу загрузить файлы большего размера. Это не с сообщением

    Ошибка во время обработки запроса: "Источник не был материализован за 5000 миллисекунд". Завершение ответа 500 Внутренняя ошибка сервера. Чтобы изменить поведение обработки исключений по умолчанию, предоставьте пользовательский ExceptionHandler. akka.stream.impl.SubscriptionTimeoutException: Подпоток Источник не был материализован в 5000 миллисекунд

Вот мои маршруты

pathEnd {
           post {
             fileUpload("attachment") {
               case (metadata, byteSource) => {
                 val writeResult: Future[MultipartUploadResult] = byteSource.runWith(client.multipartUpload("bucketname", key))
                 onSuccess(writeResult) { result =>
                   complete(result.location.toString())
                 }
               }

             }
           }

         } ~

     path("key" / Segment) {
            (sourceSystem, sourceTable, sourceId) =>
              get {
                val result: Future[ByteString] = 
         client.download("bucketname", key).runWith(Sink.head)
                onSuccess(result) {
                  complete(_)
                }
              }
          }

Попытка загрузить файл, скажем, 100 КБ приведет к извлечению усеченной версии файла обычно размером около 16-25 КБ. Любая помощь приветствуется

Изменить: Для проблемы загрузки я принял предложение Стефано и получил

[error]  found   : akka.stream.scaladsl.Source[akka.util.ByteString,akka.NotUsed]
[error]  required: akka.http.scaladsl.marshalling.ToResponseMarshallable

Это заставило это работать

complete(HttpEntity(ContentTypes.`application/octet-stream`, client.download("bucketname", key).runWith(Sink.head)))

1 ответ

1) По вопросу загрузки: по телефону

val result: Future[ByteString] = 
         client.download("bucketname", key).runWith(Sink.head)

Вы передаете все данные из S3 в память, а затем отправляете результат.

Akka-Http как поддержка потоковой передачи, которая позволяет передавать потоковые байты прямо из источника, не буферизуя их все в памяти. Более подробную информацию об этом можно найти в документации. Практически это означает, что complete Директива может принять Source[ByteString, _], как в

...
get {
  complete(client.download("bucketname", key))
}

2) По вопросу загрузки: вы можете попробовать настроить Akka HTTP akka.http.server.parsing.max-content-length установка:

# Default maximum content length which should not be exceeded by incoming request entities.
# Can be changed at runtime (to a higher or lower value) via the `HttpEntity::withSizeLimit` method.
# Note that it is not necessarily a problem to set this to a high value as all stream operations
# are always properly backpressured.
# Nevertheless you might want to apply some limit in order to prevent a single client from consuming
# an excessive amount of server resources.
#
# Set to `infinite` to completely disable entity length checks. (Even then you can still apply one
# programmatically via `withSizeLimit`.)
max-content-length = 8m

Результирующий код для проверки этого будет примерно таким:

  withoutSizeLimit {
    fileUpload("attachment") {
      ...
    }
  }
Другие вопросы по тегам