2017-09-10 12 views
1

私はPlay Framework 2.6(Scala)とAlpakka AWS S3 Connectorを使用して、ファイルをS3バケットに非同期でアップロードします。私のコードは次のようになります:Play Framework 2.6 Alpakka S3ファイルアップロード

def richUpload(extension: String, checkFunction: (String, Option[String]) => Boolean, cannedAcl: CannedAcl, bucket: String) = userAction(parse.multipartFormData(handleFilePartAsFile)).async { implicit request => 
    val s3Filename = request.user.get.id + "/" + java.util.UUID.randomUUID.toString + "." + extension 
    val fileOption = request.body.file("file").map { 
    case FilePart(key, filename, contentType, file) => 
     Logger.info(s"key = ${key}, filename = ${filename}, contentType = ${contentType}, file = $file") 
     if(checkFunction(filename, contentType)) { 
     s3Service.uploadSink(s3Filename, cannedAcl, bucket).runWith(FileIO.fromPath(file.toPath)) 
     } else { 
     throw new Exception("Upload failed") 
     } 
    } 

    fileOption match { 
    case Some(opt) => opt.map(o => Ok(s3Filename)) 
    case _ => Future.successful(BadRequest("ERROR")) 
    } 
} 

これは動作しますが、S3にアップロードする前にファイル名を返します。しかし、私はS3にアップロードした後に価値を返すことを望んでいます。解決策はありますか?

また、S3に直接ファイルをアップロードして、進捗状況を正しく表示し、一時ディスクファイルを使用しないようにすることは可能ですか?

答えて

1

はあなたのソースの周りに反転し、興味のあるmaterialized value得るためにシンクする必要がある あなたが持っている:。

  1. 、ローカルファイルからの読み込み、および読み取りが完了するとFuture[IOResult]に実体化ソースファイル。
  2. S3に書き込みを行い、S3への書き込みが完了するとFuture[MultipartUploadResult]になるシンク。

あなたは後者に興味がありますが、あなたのコードでは前者を使用しています。これは、runWith関数が、渡されたステージのマテリアライズされた値を常にパラメータとして保持するためです。

以下のサンプルスニペット内の型が、この明確にすべき:あなたはそれにmap同様のことができますFuture[MultipartUploadResult]を得て、例えば、ファイルのURIを取得するためにlocationフィールドにアクセスした後

val fileSource: Source[ByteString, Future[IOResult]]    = ??? 
    val s3Sink : Sink [ByteString, Future[MultipartUploadResult]] = ??? 

    val m1: Future[IOResult]    = s3Sink.runWith(fileSource) 
    val m2: Future[MultipartUploadResult] = fileSource.runWith(s3Sink) 

を:

​​
+0

ありがとうございました! – cutoffurmind

関連する問題