ファイルのアップロード
アップロード機能の実装
ファイルからのアップロード
アップロードしたいファイルがある場合は、localパラメータにファイルのURLを指定できます。
同じpathを持つファイルがS3にすでに存在する場合、既存のS3ファイルは上書きされます。
let dataString = "My Data"let fileName = "myFile.txt"guard let fileUrl = FileManager.default.urls( for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent(fileName)else { return }
try dataString.write( to: fileUrl, atomically: true, encoding: .utf8)
let uploadTask = Amplify.Storage.uploadFile( path: .fromString("public/example/path/myFile.txt"), local: fileUrl)データからのアップロード
データオブジェクトからファイルをアップロードするには、pathとアップロードするdataオブジェクトを指定します。
let dataString = "My Data"let data = Data(dataString.utf8)let uploadTask = Amplify.Storage.uploadData( path: .fromString("public/example/path/myFile.txt"), data: data)指定したバケットへのアップロード
bucketオプションを指定することで、特定のバケットへのアップロード操作を実行できます。
.fromOutputs(name:)を使用して、Amplify Backendでのターゲットバケットの割り当て名を表す文字列を指定できます。
// ファイルからアップロードlet uploadTask = Amplify.Storage.uploadFile( path: .fromString("public/example/path/myFile.txt"), local: fileUrl, options: .init( bucket: .fromOutputs(name: "secondBucket") ))
// データからアップロードlet uploadTask = Amplify.Storage.uploadData( path: .fromString("public/example/path/myFile.txt"), data: data, options: .init( bucket: .fromOutputs(name: "secondBucket") )).fromBucketInfo(_:)を使用してバケット名とリージョンを直接指定することもできます。
// ファイルからアップロードlet uploadTask = Amplify.Storage.uploadFile( path: .fromString("public/example/path/myFile.txt"), local: fileUrl, options: .init( bucket: .fromBucketInfo(.init( bucketName: "another-bucket-name", region: "another-bucket-region") ) ))
// データからアップロードlet uploadTask = Amplify.Storage.uploadData( path: .fromString("public/example/path/myFile.txt"), data: data, options: .init( bucket: .fromBucketInfo(.init( bucketName: "another-bucket-name", region: "another-bucket-region") ) ))アップロードの進捗を監視する
アップロードの進捗を追跡するには、以下に示すようにuploadFileまたはuploadDataから返された参照を使用します。
Task { for await progress in await uploadTask.progress { print("Progress: \(progress)") }}
let value = try await uploadTask.valueprint("Completed: \(value)")let progressSink = uploadTask .inProcessPublisher .sink { progress in print("Progress: \(progress)") }
let resultSink = uploadTask .resultPublisher .sink { if case let .failure(storageError) = $0 { print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)") } } receiveValue: { data in print("Completed: \(data)") }アップロードの一時停止、再開、キャンセル
uploadDataまたはuploadFileの呼び出しは、実際にアップロードを実行しているタスクへの参照を返します。
以下に示すように、タスクを一時停止してから再開したり、タスクをキャンセルしたりすることができます。
uploadTask.pause()uploadTask.resume()uploadTask.cancel()すべてのuploadオプション
| オプション | 型 | 説明 |
|---|---|---|
| metadata | [String: String] | 保存するオブジェクトのメタデータ。 |
| contentType | String | 保存するオブジェクトの形式を説明する標準MIMEタイプ。 |
| bucket | StorageBucket | オブジェクトを保存するバケット。 |
| progressStallTimeout | ProgressStallTimeout | アップロードの進捗停滞タイムアウトの設定。 |
セキュリティスコープリソース(iCloudから)の操作
セキュリティスコープリソースとは、iCloudやその他のクラウドストレージプロバイダーから取得したファイルを指します。iCloudに保存されているファイルへのアクセスを提供するシステムコンポーネント(例: UIDocumentBrowserViewController)を使用する際によく遭遇するファイルタイプです。
セキュリティスコープリソースをアップロードするには、以下の手順が必要です:
- startAccessingSecurityScopedResource()とstopAccessingSecurityScopedResource()を使用してセキュリティスコープファイル内のデータにアクセスする
- セキュリティスコープファイルのデータをアプリのサンドボックスに一時的に永続化する
- 一時的なURLを使用してファイルをアップロードする
- 一時的に永続化したファイルを削除する(オプション)
struct ScopedResourceFile { let name: String let data: Data}
func getTempUrls(securityScopedUrls: [URL]) -> [URL] { // 1. セキュリティスコープリソースのコンテンツをScopedResourceFile構造体に取得する let fileContents = securityScopedUrls.compactMap { url -> ScopedResourceFile? in let startAccess = url.startAccessingSecurityScopedResource() guard startAccess else { print("Issue accessing security scoped resource at :\(url)") return nil } defer { url.stopAccessingSecurityScopedResource() } do { let data = try Data(contentsOf: url) let fileName = url.lastPathComponent return ScopedResourceFile(name: fileName, data: data) } catch { print("Couldn't create Data from contents of file at url: \(url)") return nil } }
// 2. ファイルコンテンツを一時ファイルに書き込み、一時ファイルのURLを返す let localFileURLs = persistTemporaryFiles(fileContents)
// 3. アップロードしたいファイルのローカルURLが取得できました return localFileURLs}署名付きURLを使用したアップロード
method: .putを指定したgetURL APIを使用して、S3に直接ファイルをアップロードするための署名付きURLを生成できます。これは以下のような場合に便利です:
- 標準HTTPURLエンドポイントのみを受け付けるサードパーティのツールやライブラリと統合する必要がある場合
- 一時的なアップロードリンクを別のクライアントやサービスと共有したい場合
- Amplify SDKが利用できないコンテキストからアップロードする必要がある場合
import Amplifyimport AWSS3StoragePlugin
// アップロード用の署名付きURLを生成するlet uploadUrl = try await Amplify.Storage.getURL( path: .fromString("public/uploads/photo.jpg"), options: .init( pluginOptions: AWSStorageGetURLOptions( method: .put ) ))次に署名付きURLを使用して標準HTTPのPUTリクエストでファイルをアップロードします:
var request = URLRequest(url: uploadUrl)request.httpMethod = "PUT"request.httpBody = imageData
let (_, response) = try await URLSession.shared.data(for: request)let httpResponse = response as? HTTPURLResponseprint("Upload status: \(httpResponse?.statusCode ?? 0)")署名付きURLアップロードオプション
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
| pluginOptions.method | StorageAccessMethod | .get | .getはダウンロードURLを生成します。.putはアップロードURLを生成します。 |
| expires | Int | 18000 | URLが期限切れになるまでの秒数。 |
| bucket | StorageBucket | Amplify設定のデフォルトバケット | オブジェクトが保存されているバケット。 |
| pluginOptions.validateObjectExistence | Bool | false | URLを生成する前にオブジェクトが存在するかチェックするかどうか。methodが.putの場合はスキップされます。 |
マルチパートアップロード
Amplifyは5MBを超えるオブジェクトに対して自動的にAmazon S3マルチパートアップロードを実行します。S3のマルチパートアップロードの詳細については、マルチパートアップロードを使用したオブジェクトのアップロードとコピーを参照してください。