1

我对 Swift陌生,对 NIO 也很陌生。

我正在将 Swift 代码添加到需要将大量数据 (GB) 上传/下载到 AWS 的大型项目中。为此,我导入了严重依赖 NIO的 GitHub 项目Soto 。

大多数发送/接收数据的方法都是通过ByteBuffer结构来完成的。我的应用程序已经有数据要上传到 FoundationData对象中。我很难找出将这些Data对象放入 NIO 的最佳方法。

NIO ByteBuffer(2.26.0)的文档中,它指出

支持的类型:可以从 ByteBuffer 读取/写入多种类型。...开箱即用,ByteBuffer 支持例如以下类型(非详尽列表):

  • 字符串/静态字符串
  • Swift 的各种(无符号)整数类型
  • 基金会资料
  • [UInt8] 通常是 UInt8 的任何集合

但是,最新的 swift-nil 包不ByteBuffer支持 FoundationData对象。相反,它支持DispatchData对象,而对象又似乎与对象没有互操作性Data

我要避免的是复制每个数据块(一次 100 MB),只是为了在DataDispatchData类型之间进行转换。

所以...

现在我的想法是其中之一

  • 我完全迷路了,我还没有找到一个简单的解决方案

  • 解决方案是创建一个由对象DispatchData支持的子类Data

  • 使用指向对象中原始字节数组的非复制初始化器创建的ByteBuffer结构,以及一个简单地保留对象直到和对象被销毁的自定义释放器。DispatchDataDataDataByteBufferDispatchData

我将不胜感激任何想法、经验或建议(特别是如果它是选项#1)。

4

2 回答 2

1

您需要import NIOFoundationCompat获取任何适用于(或/ )Foundation等数据类型的 NIO 方法。只是包的另一个模块,因此您不需要另一个依赖项。DataJSONDecoderJSONEncoderNIOFoundationCompatswift-nio

但要明确一点,在幕后,总会有副本,但您可能不需要担心它们,副本在当今的 CPU 上非常快。如果您绝对想避免复制,则需要立即创建ByteBuffers。为了帮助您解决这个问题,您可能需要添加从哪里获取您想要通过网络发送的数据。

于 2021-03-08T18:37:44.730 回答
1

如果您担心内存使用并正在上传大型缓冲区,那么您应该使用AWSPayload.stream. 这允许您将小型流式传输ByteBuffers到 AWS。Data这是以16k 块流式传输到 S3的示例

func uploadData( _ data: Data) -> EventLoopFuture<S3.PutObjectOutput> {
    var index = 0
    let payload = AWSPayload.stream { eventLoop in
        let maxChunkSize = 16*1024
        let size = min(maxChunkSize, data.count - index)
        // are we done yet
        if size == 0 {
            return eventLoop.makeSucceededFuture(.end)
        } else {
            // create bytebuffer and return
            let byteBuffer = ByteBufferAllocator().buffer(data: data[index..<(index+size)])
            index += size
            return eventLoop.makeSucceededFuture(.byteBuffer(byteBuffer))
        }
    }
    let putRequest = S3.PutObjectRequest(body: payload, bucket: name, key: "tempfile")
    return s3.putObject(putRequest)
}

于 2021-04-15T09:49:59.133 回答