Streaming Payloads
When uploading or downloading large blocks of data it is preferable if you can stream this data instead of holding it all in memory. Soto supplies methods for streaming raw data payloads of both requests to AWS and responses from AWS. The most common use of this would be when uploading or downloading large objects to S3.
Payload object
All raw data payloads in Soto are represented by an AWSHTTPBody
object. This can be initialized with Data
, String
, ByteBuffer
or an AsyncSequence whose Element is ByteBuffer.
Request streaming
let stream = AsyncStream<ByteBuffer> {
return try await giveMeAChunkFromMyPayload()
}
let body = AWSHTTPBody(asyncSequence: stream, length: 2*1024*1024)
let request = S3.PutObjectRequest(body: body, bucket: "my-bucket", key: "my-file")
let response = try await s3.putObject(request)
If the AsyncSequence provides more or less data than you specify an error will be thrown. In some cases you might not need to provide a length.
File uploading
It is easy to implement streaming of a file using NIOFileSystem.
import _NIOFileSystem
try await FileSystem.shared.withFileHandle(forReadingAt: .init(filename)) { handle in
let fileSize = try await handle.info().size
let fileChunks = handle.readChunks(in: 0..<fileSize, chunkLength: .kilobytes(32))
let body = AWSHTTPBody(asyncSequence: fileChunks, length: fileSize)
let request = S3.PutObjectRequest(body: body, bucket: "my-bucket", key: "my-file")
let response = try await s3.putObject(request)
}
Response streaming
When a response has a streamable payload that payload will be part of the response type returned by the operation. It will be returned as a AWSHTTPBody
which conforms to AsyncSequence
.
let getRequest = S3.GetObjectRequest(bucket: "my-bucket", key: "my-file")
let response = try await s3.getObject(getRequest)
for try await buffer in response.body {
processByteBuffer(buffer)
}