scala - Play Framework 2.6 Alpakka S3 文件上传

标签 scala amazon-s3 playframework akka-stream alpakka

我使用 Play Framework 2.6 (Scala) 和 Alpakka AWS S3 连接器将文件异步上传到 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,以正确显示进度并且不使用临时磁盘文件?

最佳答案

您需要翻转源和接收器以获得 materialized value你对。。。感兴趣。 你有:

  1. 从您的本地文件读取并在完成读取文件后具体化为 Future[IOResult] 的源。
  2. 写入 S3 并在完成写入 S3 后具体化为 Future[MultipartUploadResult] 的接收器。

您对后者感兴趣,但在您的代码中使用的是前者。这是因为 runWith 函数始终将阶段的物化值作为参数传递。

下面示例片段中的类型应该阐明这一点:

  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)

在你获得一个Future[MultipartUploadResult]之后你可以用同样的方式映射并访问location字段来获取一个文件的URI,例如:

  val location: URI = fileSource.runWith(s3Sink).map(_.location)

关于scala - Play Framework 2.6 Alpakka S3 文件上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46138928/

相关文章:

scala - 将 Class[_] 转换为 Universe.Type/Symbol

java - 如何 @Inject 到主类 - Java - Play Framework

scala - Scala 导入中的双下划线是什么意思?

scala - 找不到模块 : com. eed3si9n#sbt-assembly;0.14.3

scala - 尝试写入 hdfs : Server IPC version 9 cannot communicate with client version 4 时出错

amazon-s3 - 在 S3 服务器上的摘要上运行 TensorBoard

django - 拒绝直接访问 S3 上的文件

amazon-s3 - Cloud Formation 将多个 S3 触发器添加到 LambdaConfigurations 中的同一 S3 存储桶

database - 如何在 Play 2.0 (Scala) 中使用 DATABSE_URL 进行本地连接到 mysql

angularjs - 如何配置 rhino 为 angularjs Controller 运行 jasmine 测试