2017-09-19 8 views
1

J'essaie d'utiliser akka-streams et akka-http et la bibliothèque alpakka pour télécharger/télécharger des fichiers sur Amazon S3. Je vois deux problèmes qui pourraient être liés ...Problèmes de téléchargement/téléchargement de fichiers dans akka-http/akka-streams

  • Je ne peux télécharger que de très petits fichiers, le plus grand 8kb.
  • Je ne peux pas télécharger de fichiers plus volumineux. Elle échoue avec le message

    Erreur lors du traitement de la requête: 'La source du sous-flux n'a pas été matérialisée en 5000 millisecondes'. Compléter avec 500 interne Server Erreur de réponse. Pour modifier le comportement de gestion des exceptions par défaut, fournit une exception ExceptionHandler. akka.stream.impl.SubscriptionTimeoutException: Substream Source n'a pas été matérialisé en 5000 millisecondes

Voici mes itinéraires

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(_) 
       } 
       } 
      } 

Essayer de télécharger un fichier de dire 100KB va finir par aller chercher une version tronquée du fichier habituellement de taille environ 16-25Kb Toute aide appréciée

Edit: Pour le problème de téléchargement, j'ai pris la suggestion de Stefano et j'ai obtenu

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

Cela fait fonctionner

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

Répondre

1

1) Sur la question de téléchargement: en appelant

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

vous diffusez tous les données de S3 en mémoire, puis servir le résultat.

Akka-Http en tant que support de diffusion en continu qui vous permet de diffuser des octets directement à partir d'une source, sans les mettre tous en mémoire tampon. Plus d'informations à ce sujet peuvent être trouvées dans le docs. En pratique, cela signifie que la directive complete peut prendre Source[ByteString, _], comme dans

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

2) Sur la question de téléchargement: vous pouvez essayer de modifier Akka HTTP paramètre 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 

code résultant pour tester cette serait quelque chose le long de:

withoutSizeLimit { 
    fileUpload("attachment") { 
     ... 
    } 
    }