我有一个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 Stream,Akka HTTP或Play做到这一点?我可以利用Alpakka图书馆吗?
根据拉蒙的答案编辑的临时文件:
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)
答案 0 :(得分:0)
第一步是创建akka
流Source
of the bucket contents:
type Key = String
def bucketNameToKeySource(bucket : String) : Source[Key, _] =
S3.listBucket(bucket, None)
.map(_.key)
现在可以将其与S3 download capabilities和flatMapConcat
组合:
def bucketNameToFileContents(bucket : String) : Source[ByteString, _] =
bucketNameToKeySource(bucket)
.map(key => S3.download(bucket, key))
.map(_.getOrElse(Source.empty[ByteString])
.flatMapConcat(identity)
此功能现在可以合并到您的Route
中。该问题要求“从服务器到客户端打开一个zip流”,因此使用encodeRespose
:
def bucketNameToRoute(parentBucketName : String) : Route =
encodeResponse {
path ("download" / Segment) { childBucketName =>
val bucketName = parentBucketName + "/" + childBucketName
val byteStrSource = bucketNameToFileContents(bucketName)
complete(OK -> byteStrSource)
}
}