Import AWS SDK for Swift

Ensure that Swift 5.7 or a higher version is installed, as well as OpenSSL v1.x.

The AWS SDK for Swift supports the following platforms:

  • iOS & iPadOS 13.0 or higher
  • macOS 10.15 or higher
  • Ubuntu Linux 16.04 LTS or higher
  • Amazon Linux 2 or higher

Initialize a Swift project

swift package init --type executable

To add the AWS SDK for Swift to your Swift project, you can use the Package.swift file.

// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "aws-swift-sdk-test-examples",
    dependencies: [
        .package(
            url: "https://github.com/awslabs/aws-sdk-swift",
            from: "0.36.0"
        )
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .executableTarget(
            name: "aws-swift-sdk-test-examples",
            dependencies: [
                .product(name: "AWSS3", package: "aws-sdk-swift"),
                .product(name: "AWSSTS", package: "aws-sdk-swift")],
            path: "Sources")
    ]
)

For each code example that follows,create the code under the Sources/entry.swift ,then execute

swift run

UploadObject

Client-side upload

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let uploadRequest = PutObjectInput(
            bucket: "<Bucket>",
            key: "<Key>"
        )
        let url = try await uploadRequest.presignURL(config: config, expiration: 3600)
        print("\(String(describing: url))")
    }
}

his code will generate a pre-signed client-side upload URL, valid for 1 hours, which the client can use to send an PUT request and upload a file within the expiration time.

The following is an example of uploading a file using curl:

curl -X PUT --upload-file "<path/to/file>" "<presigned url>"

Server-side upload

PutObject(file)

Create Sources/entry.swift

import Foundation
import ClientRuntime
import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        guard let file = FileHandle(forReadingAtPath: "<path/to/upload>") else {
            return
        }
        let response = try await client.putObject(input: PutObjectInput(
            body: ByteStream.from(fileHandle: file),
            bucket: "<Bucket>",
            key: "<Key>"
        ))
        print("ETag: \(String(describing: response.eTag))")
    }
}

PutObject(stream)

Create Sources/entry.swift

import Foundation
import ClientRuntime
import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let response = try await client.putObject(input: PutObjectInput(
            body: ByteStream.data("Hello from SUFY S3!".data(using: .utf8)),
            bucket: "<Bucket>",
            key: "<Key>"
        ))
        print("ETag: \(String(describing: response.eTag))")
    }
}

MultipartUpload(file)

Create Sources/entry.swift

import Foundation
import ClientRuntime
import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        guard let file = FileHandle(forReadingAtPath: "<path/to/upload>") else {
            return
        }

        let createMultipartUploadResponse = try await client.createMultipartUpload(input: CreateMultipartUploadInput(
            bucket: "<Bucket>",
            key: "<Key>"
        ))
        if createMultipartUploadResponse.uploadId == nil {
            return
        }

        let PART_SIZE = 5 * 1024 * 1024 // part size is 5 MB
        var parts = [S3ClientTypes.CompletedPart]()
        var partNum = 1
        // The example given here is a serial multipart upload. You can modify it to perform a parallel multipart upload to further improve the upload speed.
        while true {
            let data = file.readData(ofLength: PART_SIZE)
            if data.count == 0 {
                break
            }

            let uploadPartResponse = try await client.uploadPart(input: UploadPartInput(
                body: ByteStream.data(data),
                bucket: createMultipartUploadResponse.bucket,
                key: createMultipartUploadResponse.key,
                partNumber: partNum,
                uploadId: createMultipartUploadResponse.uploadId
            ))
            if uploadPartResponse.eTag == nil {
                return
            }

            parts.append(S3ClientTypes.CompletedPart(
                eTag: uploadPartResponse.eTag,
                partNumber: partNum
            ))
            partNum += 1
        }

        let completeMultipartUploadResponse = try await client.completeMultipartUpload(input: CompleteMultipartUploadInput(
            bucket: createMultipartUploadResponse.bucket,
            key: createMultipartUploadResponse.key,
            multipartUpload: S3ClientTypes.CompletedMultipartUpload(parts: parts),
            uploadId: createMultipartUploadResponse.uploadId
        ))
        print("ETag: \(String(describing: completeMultipartUploadResponse.eTag)))")
    }
}

GetObject

Client-side get object

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let downloadRequest = GetObjectInput(
            bucket: "<Bucket>",
            key: "<Key>"
        )
        let url = try await downloadRequest.presignURL(config: config, expiration: 3600)
        print("\(String(describing: url))")
    }
}

This code will generate a pre-signed client-side download URL, valid for 1 hours, which the client can use to send an GET request and download the file within the expiration time.

The following is an example of downloading a file using curl:

curl -o "<path/to/download>" "<presigned url>"

Server-side get object

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let response = try await client.getObject(input: GetObjectInput(
            bucket: "<Bucket>",
            key: "<Key>"
        ))
        guard let body = response.body,
              let data = try await body.readData() else {
            return
        }
        try data.write(to: URL(fileURLWithPath: "<path/to/download>"))
        print("ETag: \(String(describing: response.eTag))")
    }
}

ObjectOperations

HeadObject

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let response = try await client.headObject(input: HeadObjectInput(
            bucket: "<Bucket>",
            key: "<Key>"
        ))
        print("ETag: \(String(describing: response.eTag))")
    }
}

ChangeStorageClass

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let _ = try await client.copyObject(input: CopyObjectInput(
            bucket: "<Bucket>",
            copySource: "/<Bucket>/<Key>",
            key: "<Key>",
            metadataDirective: .replace,
            storageClass: .glacier
        ))
        print("Done")
    }
}

CopyObject

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let _ = try await client.copyObject(input: CopyObjectInput(
            bucket: "<ToBucket>",
            copySource: "/<FromBucket>/<FromKey>",
            key: "<ToKey>",
            metadataDirective: .copy
        ))
        print("Done")
    }
}

CopyObject(> 5GB)

Create Sources/entry.swift

import Foundation
import ClientRuntime
import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let headObjectResponse = try await client.headObject(input: HeadObjectInput(
            bucket: "<FromBucket>",
            key: "<FromKey>"
        ))

        let createMultipartUploadResponse = try await client.createMultipartUpload(input: CreateMultipartUploadInput(
            bucket: "<ToBucket>",
            key: "<ToKey>"
        ))
        if createMultipartUploadResponse.uploadId == nil {
            return
        }

        let PART_SIZE = 5 * 1024 * 1024 // part size is 5 MB
        var parts = [S3ClientTypes.CompletedPart]()
        var partNum = 1
        var copied = 0

        // The example given here is a serial multipart copy. You can modify it to perform a parallel multipart copy to further improve the copy speed.
        while copied < headObjectResponse.contentLength! {
            let partSize = min(headObjectResponse.contentLength! - copied, PART_SIZE)

            let uploadPartCopyResponse = try await client.uploadPartCopy(input: UploadPartCopyInput(
                bucket: createMultipartUploadResponse.bucket,
                copySource: "/<FromBucket>/<FromKey>",
                copySourceRange: "bytes=\(copied)-\(copied+partSize-1)",
                key: createMultipartUploadResponse.key,
                partNumber: partNum,
                uploadId: createMultipartUploadResponse.uploadId
            ))
            if uploadPartCopyResponse.copyPartResult?.eTag == nil {
                return
            }

            parts.append(S3ClientTypes.CompletedPart(
                eTag: uploadPartCopyResponse.copyPartResult?.eTag,
                partNumber: partNum
            ))
            partNum += 1
            copied += partSize
        }

        let completeMultipartUploadResponse = try await client.completeMultipartUpload(input: CompleteMultipartUploadInput(
            bucket: createMultipartUploadResponse.bucket,
            key: createMultipartUploadResponse.key,
            multipartUpload: S3ClientTypes.CompletedMultipartUpload(parts: parts),
            uploadId: createMultipartUploadResponse.uploadId
        ))
        print("ETag: \(String(describing: completeMultipartUploadResponse.eTag)))")
    }
}

DeleteObject

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let _ = try await client.deleteObject(input: DeleteObjectInput(
            bucket: "<Bucket>",
            key: "<Key>"
        ))
        print("Done")
    }
}

ListObjects

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let response = try await client.listObjectsV2(input: ListObjectsV2Input(
            bucket: "<Bucket>",
            prefix: "<KeyPrefix>"
        ))
        for content in response.contents ?? [] {
            print("Key: \(String(describing: content.key))")
            print("ETag: \(String(describing: content.eTag))")
        }
    }
}

DeleteObject

Create Sources/entry.swift

import AWSClientRuntime
import AWSS3

@main
struct Main {
    static func main() async throws {
        let config = try await S3Client.S3ClientConfiguration()
        config.credentialsProvider = try StaticCredentialsProvider(Credentials(
            accessKey: "<AccessKey>",
            secret: "<SecretKey>"
        ))
        config.region = "ap-southeast-2", // Asia Pacific (Hanoi) RegionID
        config.endpoint = "https://mos.ap-southeast-2.sufybkt.com", // Asia Pacific (Hanoi) Endpoint
        let client = S3Client(config: config)
        let _ = try await client.deleteObjects(input: DeleteObjectsInput(
            bucket: "<Bucket>",
            delete: S3ClientTypes.Delete(objects: [
                S3ClientTypes.ObjectIdentifier(key: "<Key1>"),
                S3ClientTypes.ObjectIdentifier(key: "<Key2>"),
                S3ClientTypes.ObjectIdentifier(key: "<Key3>"),
            ])
        ))
        print("Done")
    }
}