文件 AWS 開發套件範例 GitHub 儲存庫中有更多可用的 AWS SDK 範例
本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用適用於 Swift 的 SDK 的 Amazon S3 範例
下列程式碼範例示範如何使用適用於 Swift 的 AWS SDK 搭配 Amazon S3 來執行動作和實作常見案例。
基本概念是程式碼範例,這些範例說明如何在服務內執行基本操作。
Actions 是大型程式的程式碼摘錄,必須在內容中執行。雖然動作會告訴您如何呼叫個別服務函數,但您可以在其相關情境中查看內容中的動作。
案例是向您展示如何呼叫服務中的多個函數或與其他 AWS 服務組合來完成特定任務的程式碼範例。
每個範例都包含完整原始程式碼的連結,您可以在其中找到如何在內容中設定和執行程式碼的指示。
基本概念
以下程式碼範例顯示做法:
建立儲存貯體並上傳檔案到該儲存貯體。
從儲存貯體下載物件。
將物件複製至儲存貯體中的子文件夾。
列出儲存貯體中的物件。
刪除儲存貯體物件和該儲存貯體。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 import Foundation import AWSS3 import Smithy import ClientRuntime /// A class containing all the code that interacts with the AWS SDK for Swift. public class ServiceHandler { let configuration: S3Client.S3ClientConfiguration let client: S3Client enum HandlerError: Error { case getObjectBody(String) case readGetObjectBody(String) case missingContents(String) } /// Initialize and return a new ``ServiceHandler`` object, which is used to drive the AWS calls /// used for the example. /// /// - Returns: A new ``ServiceHandler`` object, ready to be called to /// execute AWS operations. public init() async throws { do { configuration = try await S3Client.S3ClientConfiguration() // configuration.region = "us-east-2" // Uncomment this to set the region programmatically. client = S3Client(config: configuration) } catch { print("ERROR: ", dump(error, name: "Initializing S3 client")) throw error } } /// Create a new user given the specified name. /// /// - Parameters: /// - name: Name of the bucket to create. /// Throws an exception if an error occurs. public func createBucket(name: String) async throws { var input = CreateBucketInput( bucket: name ) // For regions other than "us-east-1", you must set the locationConstraint in the createBucketConfiguration. // For more information, see LocationConstraint in the S3 API guide. // https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html#API_CreateBucket_RequestBody if let region = configuration.region { if region != "us-east-1" { input.createBucketConfiguration = S3ClientTypes.CreateBucketConfiguration(locationConstraint: S3ClientTypes.BucketLocationConstraint(rawValue: region)) } } do { _ = try await client.createBucket(input: input) } catch let error as BucketAlreadyOwnedByYou { print("The bucket '\(name)' already exists and is owned by you. You may wish to ignore this exception.") throw error } catch { print("ERROR: ", dump(error, name: "Creating a bucket")) throw error } } /// Delete a bucket. /// - Parameter name: Name of the bucket to delete. public func deleteBucket(name: String) async throws { let input = DeleteBucketInput( bucket: name ) do { _ = try await client.deleteBucket(input: input) } catch { print("ERROR: ", dump(error, name: "Deleting a bucket")) throw error } } /// Upload a file from local storage to the bucket. /// - Parameters: /// - bucket: Name of the bucket to upload the file to. /// - key: Name of the file to create. /// - file: Path name of the file to upload. public func uploadFile(bucket: String, key: String, file: String) async throws { let fileUrl = URL(fileURLWithPath: file) do { let fileData = try Data(contentsOf: fileUrl) let dataStream = ByteStream.data(fileData) let input = PutObjectInput( body: dataStream, bucket: bucket, key: key ) _ = try await client.putObject(input: input) } catch { print("ERROR: ", dump(error, name: "Putting an object.")) throw error } } /// Create a file in the specified bucket with the given name. The new /// file's contents are uploaded from a `Data` object. /// /// - Parameters: /// - bucket: Name of the bucket to create a file in. /// - key: Name of the file to create. /// - data: A `Data` object to write into the new file. public func createFile(bucket: String, key: String, withData data: Data) async throws { let dataStream = ByteStream.data(data) let input = PutObjectInput( body: dataStream, bucket: bucket, key: key ) do { _ = try await client.putObject(input: input) } catch { print("ERROR: ", dump(error, name: "Putting an object.")) throw error } } /// Download the named file to the given directory on the local device. /// /// - Parameters: /// - bucket: Name of the bucket that contains the file to be copied. /// - key: The name of the file to copy from the bucket. /// - to: The path of the directory on the local device where you want to /// download the file. public func downloadFile(bucket: String, key: String, to: String) async throws { let fileUrl = URL(fileURLWithPath: to).appendingPathComponent(key) let input = GetObjectInput( bucket: bucket, key: key ) do { let output = try await client.getObject(input: input) guard let body = output.body else { throw HandlerError.getObjectBody("GetObjectInput missing body.") } guard let data = try await body.readData() else { throw HandlerError.readGetObjectBody("GetObjectInput unable to read data.") } try data.write(to: fileUrl) } catch { print("ERROR: ", dump(error, name: "Downloading a file.")) throw error } } /// Read the specified file from the given S3 bucket into a Swift /// `Data` object. /// /// - Parameters: /// - bucket: Name of the bucket containing the file to read. /// - key: Name of the file within the bucket to read. /// /// - Returns: A `Data` object containing the complete file data. public func readFile(bucket: String, key: String) async throws -> Data { let input = GetObjectInput( bucket: bucket, key: key ) do { let output = try await client.getObject(input: input) guard let body = output.body else { throw HandlerError.getObjectBody("GetObjectInput missing body.") } guard let data = try await body.readData() else { throw HandlerError.readGetObjectBody("GetObjectInput unable to read data.") } return data } catch { print("ERROR: ", dump(error, name: "Reading a file.")) throw error } } /// Copy a file from one bucket to another. /// /// - Parameters: /// - sourceBucket: Name of the bucket containing the source file. /// - name: Name of the source file. /// - destBucket: Name of the bucket to copy the file into. public func copyFile(from sourceBucket: String, name: String, to destBucket: String) async throws { let srcUrl = ("\(sourceBucket)/\(name)").addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) let input = CopyObjectInput( bucket: destBucket, copySource: srcUrl, key: name ) do { _ = try await client.copyObject(input: input) } catch { print("ERROR: ", dump(error, name: "Copying an object.")) throw error } } /// Deletes the specified file from Amazon S3. /// /// - Parameters: /// - bucket: Name of the bucket containing the file to delete. /// - key: Name of the file to delete. /// public func deleteFile(bucket: String, key: String) async throws { let input = DeleteObjectInput( bucket: bucket, key: key ) do { _ = try await client.deleteObject(input: input) } catch { print("ERROR: ", dump(error, name: "Deleting a file.")) throw error } } /// Returns an array of strings, each naming one file in the /// specified bucket. /// /// - Parameter bucket: Name of the bucket to get a file listing for. /// - Returns: An array of `String` objects, each giving the name of /// one file contained in the bucket. public func listBucketFiles(bucket: String) async throws -> [String] { do { let input = ListObjectsV2Input( bucket: bucket ) // Use "Paginated" to get all the objects. // This lets the SDK handle the 'continuationToken' in "ListObjectsV2Output". let output = client.listObjectsV2Paginated(input: input) var names: [String] = [] for try await page in output { guard let objList = page.contents else { print("ERROR: listObjectsV2Paginated returned nil contents.") continue } for obj in objList { if let objName = obj.key { names.append(objName) } } } return names } catch { print("ERROR: ", dump(error, name: "Listing objects.")) throw error } } }
import AWSS3 import Foundation import ServiceHandler import ArgumentParser /// The command-line arguments and options available for this /// example command. struct ExampleCommand: ParsableCommand { @Argument(help: "Name of the S3 bucket to create") var bucketName: String @Argument(help: "Pathname of the file to upload to the S3 bucket") var uploadSource: String @Argument(help: "The name (key) to give the file in the S3 bucket") var objName: String @Argument(help: "S3 bucket to copy the object to") var destBucket: String @Argument(help: "Directory where you want to download the file from the S3 bucket") var downloadDir: String static var configuration = CommandConfiguration( commandName: "s3-basics", abstract: "Demonstrates a series of basic AWS S3 functions.", discussion: """ Performs the following Amazon S3 commands: * `CreateBucket` * `PutObject` * `GetObject` * `CopyObject` * `ListObjects` * `DeleteObjects` * `DeleteBucket` """ ) /// Called by ``main()`` to do the actual running of the AWS /// example. func runAsync() async throws { let serviceHandler = try await ServiceHandler() // 1. Create the bucket. print("Creating the bucket \(bucketName)...") try await serviceHandler.createBucket(name: bucketName) // 2. Upload a file to the bucket. print("Uploading the file \(uploadSource)...") try await serviceHandler.uploadFile(bucket: bucketName, key: objName, file: uploadSource) // 3. Download the file. print("Downloading the file \(objName) to \(downloadDir)...") try await serviceHandler.downloadFile(bucket: bucketName, key: objName, to: downloadDir) // 4. Copy the file to another bucket. print("Copying the file to the bucket \(destBucket)...") try await serviceHandler.copyFile(from: bucketName, name: objName, to: destBucket) // 5. List the contents of the bucket. print("Getting a list of the files in the bucket \(bucketName)") let fileList = try await serviceHandler.listBucketFiles(bucket: bucketName) let numFiles = fileList.count if numFiles != 0 { print("\(numFiles) file\((numFiles > 1) ? "s" : "") in bucket \(bucketName):") for name in fileList { print(" \(name)") } } else { print("No files found in bucket \(bucketName)") } // 6. Delete the objects from the bucket. print("Deleting the file \(objName) from the bucket \(bucketName)...") try await serviceHandler.deleteFile(bucket: bucketName, key: objName) print("Deleting the file \(objName) from the bucket \(destBucket)...") try await serviceHandler.deleteFile(bucket: destBucket, key: objName) // 7. Delete the bucket. print("Deleting the bucket \(bucketName)...") try await serviceHandler.deleteBucket(name: bucketName) print("Done.") } } // // Main program entry point. // @main struct Main { static func main() async { let args = Array(CommandLine.arguments.dropFirst()) do { let command = try ExampleCommand.parse(args) try await command.runAsync() } catch { ExampleCommand.exit(withError: error) } } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的下列主題。
-
動作
下列程式碼範例示範如何使用 CopyObject
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func copyFile(from sourceBucket: String, name: String, to destBucket: String) async throws { let srcUrl = ("\(sourceBucket)/\(name)").addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) let input = CopyObjectInput( bucket: destBucket, copySource: srcUrl, key: name ) do { _ = try await client.copyObject(input: input) } catch { print("ERROR: ", dump(error, name: "Copying an object.")) throw error } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的CopyObject
。
-
下列程式碼範例示範如何使用 CreateBucket
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func createBucket(name: String) async throws { var input = CreateBucketInput( bucket: name ) // For regions other than "us-east-1", you must set the locationConstraint in the createBucketConfiguration. // For more information, see LocationConstraint in the S3 API guide. // https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html#API_CreateBucket_RequestBody if let region = configuration.region { if region != "us-east-1" { input.createBucketConfiguration = S3ClientTypes.CreateBucketConfiguration(locationConstraint: S3ClientTypes.BucketLocationConstraint(rawValue: region)) } } do { _ = try await client.createBucket(input: input) } catch let error as BucketAlreadyOwnedByYou { print("The bucket '\(name)' already exists and is owned by you. You may wish to ignore this exception.") throw error } catch { print("ERROR: ", dump(error, name: "Creating a bucket")) throw error } }
-
如需 API 詳細資訊,請參閱 《適用於 Swift 的AWS SDK API 參考》中的 CreateBucket
。
-
下列程式碼範例示範如何使用 DeleteBucket
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func deleteBucket(name: String) async throws { let input = DeleteBucketInput( bucket: name ) do { _ = try await client.deleteBucket(input: input) } catch { print("ERROR: ", dump(error, name: "Deleting a bucket")) throw error } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的 DeleteBucket
。
-
下列程式碼範例示範如何使用 DeleteObject
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func deleteFile(bucket: String, key: String) async throws { let input = DeleteObjectInput( bucket: bucket, key: key ) do { _ = try await client.deleteObject(input: input) } catch { print("ERROR: ", dump(error, name: "Deleting a file.")) throw error } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的 DeleteObject
。
-
下列程式碼範例示範如何使用 DeleteObjects
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func deleteObjects(bucket: String, keys: [String]) async throws { let input = DeleteObjectsInput( bucket: bucket, delete: S3ClientTypes.Delete( objects: keys.map { S3ClientTypes.ObjectIdentifier(key: $0) }, quiet: true ) ) do { _ = try await client.deleteObjects(input: input) } catch { print("ERROR: deleteObjects:", dump(error)) throw error } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的 DeleteObjects
。
-
下列程式碼範例示範如何使用 GetObject
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func downloadFile(bucket: String, key: String, to: String) async throws { let fileUrl = URL(fileURLWithPath: to).appendingPathComponent(key) let input = GetObjectInput( bucket: bucket, key: key ) do { let output = try await client.getObject(input: input) guard let body = output.body else { throw HandlerError.getObjectBody("GetObjectInput missing body.") } guard let data = try await body.readData() else { throw HandlerError.readGetObjectBody("GetObjectInput unable to read data.") } try data.write(to: fileUrl) } catch { print("ERROR: ", dump(error, name: "Downloading a file.")) throw error } }
import AWSS3 public func readFile(bucket: String, key: String) async throws -> Data { let input = GetObjectInput( bucket: bucket, key: key ) do { let output = try await client.getObject(input: input) guard let body = output.body else { throw HandlerError.getObjectBody("GetObjectInput missing body.") } guard let data = try await body.readData() else { throw HandlerError.readGetObjectBody("GetObjectInput unable to read data.") } return data } catch { print("ERROR: ", dump(error, name: "Reading a file.")) throw error } }
-
如需 API 詳細資訊,請參閱 《適用於 Swift 的AWS SDK API 參考》中的 GetObject
。
-
下列程式碼範例示範如何使用 ListBuckets
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 /// Return an array containing information about every available bucket. /// /// - Returns: An array of ``S3ClientTypes.Bucket`` objects describing /// each bucket. public func getAllBuckets() async throws -> [S3ClientTypes.Bucket] { return try await client.listBuckets(input: ListBucketsInput()) }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的 ListBuckets
。
-
下列程式碼範例示範如何使用 ListObjectsV2
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 public func listBucketFiles(bucket: String) async throws -> [String] { do { let input = ListObjectsV2Input( bucket: bucket ) // Use "Paginated" to get all the objects. // This lets the SDK handle the 'continuationToken' in "ListObjectsV2Output". let output = client.listObjectsV2Paginated(input: input) var names: [String] = [] for try await page in output { guard let objList = page.contents else { print("ERROR: listObjectsV2Paginated returned nil contents.") continue } for obj in objList { if let objName = obj.key { names.append(objName) } } } return names } catch { print("ERROR: ", dump(error, name: "Listing objects.")) throw error } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的 ListObjectsV2
。
-
下列程式碼範例示範如何使用 PutObject
。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import AWSS3 import Smithy public func uploadFile(bucket: String, key: String, file: String) async throws { let fileUrl = URL(fileURLWithPath: file) do { let fileData = try Data(contentsOf: fileUrl) let dataStream = ByteStream.data(fileData) let input = PutObjectInput( body: dataStream, bucket: bucket, key: key ) _ = try await client.putObject(input: input) } catch { print("ERROR: ", dump(error, name: "Putting an object.")) throw error } }
import AWSS3 import Smithy public func createFile(bucket: String, key: String, withData data: Data) async throws { let dataStream = ByteStream.data(data) let input = PutObjectInput( body: dataStream, bucket: bucket, key: key ) do { _ = try await client.putObject(input: input) } catch { print("ERROR: ", dump(error, name: "Putting an object.")) throw error } }
-
如需 API 詳細資訊,請參閱《適用於 Swift 的AWS SDK API 參考》中的 PutObject
。
-
案例
下列程式碼範例示範如何從 Amazon S3 物件下載未知大小的串流。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import ArgumentParser import AWSClientRuntime import AWSS3 import Foundation import Smithy import SmithyHTTPAPI import SmithyStreams /// Download a file from the specified bucket. /// /// - Parameters: /// - bucket: The Amazon S3 bucket name to get the file from. /// - key: The name (or path) of the file to download from the bucket. /// - destPath: The pathname on the local filesystem at which to store /// the downloaded file. func downloadFile(bucket: String, key: String, destPath: String?) async throws { let fileURL: URL // If no destination path was provided, use the key as the name to use // for the file in the downloads folder. if destPath == nil { do { try fileURL = FileManager.default.url( for: .downloadsDirectory, in: .userDomainMask, appropriateFor: URL(string: key), create: true ).appendingPathComponent(key) } catch { throw TransferError.directoryError } } else { fileURL = URL(fileURLWithPath: destPath!) } let config = try await S3Client.S3ClientConfiguration(region: region) let s3Client = S3Client(config: config) // Create a `FileHandle` referencing the local destination. Then // create a `ByteStream` from that. FileManager.default.createFile(atPath: fileURL.path, contents: nil, attributes: nil) let fileHandle = try FileHandle(forWritingTo: fileURL) // Download the file using `GetObject`. let getInput = GetObjectInput( bucket: bucket, key: key ) do { let getOutput = try await s3Client.getObject(input: getInput) guard let body = getOutput.body else { throw TransferError.downloadError("Error: No data returned for download") } // If the body is returned as a `Data` object, write that to the // file. If it's a stream, read the stream chunk by chunk, // appending each chunk to the destination file. switch body { case .data: guard let data = try await body.readData() else { throw TransferError.downloadError("Download error") } // Write the `Data` to the file. do { try data.write(to: fileURL) } catch { throw TransferError.writeError } break case .stream(let stream as ReadableStream): while (true) { let chunk = try await stream.readAsync(upToCount: 5 * 1024 * 1024) guard let chunk = chunk else { break } // Write the chunk to the destination file. do { try fileHandle.write(contentsOf: chunk) } catch { throw TransferError.writeError } } break default: throw TransferError.downloadError("Received data is unknown object type") } } catch { throw TransferError.downloadError("Error downloading the file: \(error)") } print("File downloaded to \(fileURL.path).") }
下列程式碼範例顯示如何將大小不明的串流上傳至 Amazon S3 物件。
- SDK for Swift
-
注意
GitHub 上提供更多範例。尋找完整範例,並了解如何在 AWS 程式碼範例儲存庫
中設定和執行。 import ArgumentParser import AWSClientRuntime import AWSS3 import Foundation import Smithy import SmithyHTTPAPI import SmithyStreams /// Upload a file to the specified bucket. /// /// - Parameters: /// - bucket: The Amazon S3 bucket name to store the file into. /// - key: The name (or path) of the file to upload to in the `bucket`. /// - sourcePath: The pathname on the local filesystem of the file to /// upload. func uploadFile(sourcePath: String, bucket: String, key: String?) async throws { let fileURL: URL = URL(fileURLWithPath: sourcePath) let fileName: String // If no key was provided, use the last component of the filename. if key == nil { fileName = fileURL.lastPathComponent } else { fileName = key! } let s3Client = try await S3Client() // Create a FileHandle for the source file. let fileHandle = FileHandle(forReadingAtPath: sourcePath) guard let fileHandle = fileHandle else { throw TransferError.readError } // Create a byte stream to retrieve the file's contents. This uses the // Smithy FileStream and ByteStream types. let stream = FileStream(fileHandle: fileHandle) let body = ByteStream.stream(stream) // Create a `PutObjectInput` with the ByteStream as the body of the // request's data. The AWS SDK for Swift will handle sending the // entire file in chunks, regardless of its size. let putInput = PutObjectInput( body: body, bucket: bucket, key: fileName ) do { _ = try await s3Client.putObject(input: putInput) } catch { throw TransferError.uploadError("Error uploading the file: \(error)") } print("File uploaded to \(fileURL.path).") }