Amazon web services 通过Akka HTTP或Play以zip格式从S3下载多个文件

Amazon web services 通过Akka HTTP或Play以zip格式从S3下载多个文件,amazon-web-services,playframework,akka-stream,akka-http,alpakka,Amazon Web Services,Playframework,Akka Stream,Akka Http,Alpakka,我有一个S3结构,它是Spark作业的结果,它编写了分区CSV文件,如下所示 bucketA output cleaned-data1 part000....csv part001....csv part002....csv cleaned-data2 ..... 我需要的是能够有一个指向输出文件名的Akka HTTP端点,以zip文件的形式下载所有部件:https://..../download/cleaned-data1

我有一个S3结构,它是Spark作业的结果,它编写了分区CSV文件,如下所示

bucketA
  output
    cleaned-data1
      part000....csv
      part001....csv
      part002....csv
    cleaned-data2
      .....
我需要的是能够有一个指向输出文件名的Akka HTTP端点,以zip文件的形式下载所有部件:
https://..../download/cleaned-data1

调用此端点时,理想情况下我希望:

  • 打开从服务器到客户端浏览器的zip流

  • 打开部件文件并将字节流到zip流中,直接发送到客户端,而无需在服务器上进行任何缓冲,以避免内存问题

  • 所有部件的未压缩总大小可达30GB

    有没有办法通过Akka流、Akka HTTP或Play实现这一点?我能利用阿尔帕卡图书馆吗

    根据Ramon的回答编辑的临时文件:

      def bucketNameToFileContents(bucket : String) : Source[ByteString, _] =
        bucketNameToKeySource(bucket)
          .map(key => S3.download(bucket, key))
          .map(x => x.map(y => y.fold(Source.empty[ByteString])(_._1)))
          .flatMapConcat(identity)
          .flatMapConcat(identity)
    

    第一步是创建
    akka
    流:

    现在可以将其与和结合使用:

    此功能现在可以合并到您的
    路线中
    。该问题要求“打开从服务器到客户端的zip流”,因此使用
    encodeResponse

    def bucketNameToRoute(parentBucketName : String) : Route = 
      encodeResponse {
        path ("download" / Segment) { childBucketName =>
    
          val bucketName = parentBucketName + "/" + childBucketName
    
          val byteStrSource = bucketNameToFileContents(bucketName)
    
          complete(OK -> byteStrSource)
        } 
      }
    

    谢谢,雷蒙!我在第二个代码段的第三行发现编译错误:
    .map(u.getOrElse(Source.empty[ByteString])
    ,因为内部var
    \uu
    映射的类型是
    Source[Option[X]]
    。我会错过任何隐式导入吗?@suriyanto不客气。我没有尝试编译/运行代码片段。它们只是为了演示,所以可能会有一些小错误……Ramon,我在我的原始帖子中介绍了我如何更改
    bucketNameToFileContents
    。与其在Akka Http中公开此流,如何让我无法通过播放使用?这将是现有基于播放的服务的一部分。@suriyanto我不知道,我从未使用过
    Play
    def bucketNameToFileContents(bucket : String) : Source[ByteString, _] = 
      bucketNameToKeySource(bucket)
        .map(key => S3.download(bucket, key))
        .map(_.getOrElse(Source.empty[ByteString])
        .flatMapConcat(identity)
    
    def bucketNameToRoute(parentBucketName : String) : Route = 
      encodeResponse {
        path ("download" / Segment) { childBucketName =>
    
          val bucketName = parentBucketName + "/" + childBucketName
    
          val byteStrSource = bucketNameToFileContents(bucketName)
    
          complete(OK -> byteStrSource)
        } 
      }