使用AWSS3TransferUtility上传音频至AWS S3 Bucket时遭遇Error Domain=com.amazonaws.AWSS3TransferUtilityErrorDomain Code=2错误
First, let's break down what that error means: Error Domain=com.amazonaws.AWSS3TransferUtilityErrorDomain Code=2 typically points to one of these issues: invalid request signing, insufficient permissions, misordered AWS service initialization, or mismatched resource configurations. Let's walk through fixing this step by step, including adapting your code for audio file uploads.
Step 1: Fix AWS Service Initialization Order
Your current code registers the TransferUtility before setting the global default service configuration. This causes the TransferUtility to use an outdated default config, which is a common source of Code 2 errors. Reorder your setup like this:
// First, initialize credentials and global configuration let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast2, identityPoolId:"us-east-2:fe41c293-df49-49a4-886d-094f2cd8d0fd") guard let configuration = AWSServiceConfiguration(region:.USEast2, credentialsProvider:credentialsProvider) else { print("Failed to create AWS service configuration") return } AWSServiceManager.default().defaultServiceConfiguration = configuration // THEN register and retrieve the TransferUtility let tuConf = AWSS3TransferUtilityConfiguration() AWSS3TransferUtility.register( with: configuration, transferUtilityConfiguration: tuConf, forKey: "transfer-utility-audio-upload" ) guard let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "transfer-utility-audio-upload") else { print("Failed to initialize TransferUtility") return }
Step 2: Verify Cognito & S3 Permissions
Code 2 often pops up when your Cognito identity pool lacks the necessary S3 upload permissions.
- Go to the IAM Console and find the role linked to your Cognito identity pool (either authenticated or unauthenticated, depending on your app's flow).
- Attach a policy that allows uploads to your target bucket path:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:PutObjectAcl" ], "Resource": "arn:aws:s3:::testingimageupload/private/Abhay/*" } ] }
- Double-check that your S3 bucket's policy doesn't block access from this role (if you have a bucket policy configured).
Step 3: Adapt Code for Audio File Uploads
Your original code is built for images—here's a revised version tailored for audio, with key fixes:
func uploadAudioFile(fromFileURL fileURL: URL) { // 1. Initialize AWS config first (fixed order) let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast2, identityPoolId:"us-east-2:fe41c293-df49-49a4-886d-094f2cd8d0fd") guard let configuration = AWSServiceConfiguration(region:.USEast2, credentialsProvider:credentialsProvider) else { print("Failed to create AWS configuration") return } AWSServiceManager.default().defaultServiceConfiguration = configuration // 2. Register TransferUtility let tuConf = AWSS3TransferUtilityConfiguration() AWSS3TransferUtility.register( with: configuration, transferUtilityConfiguration: tuConf, forKey: "transfer-utility-audio-upload" ) guard let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "transfer-utility-audio-upload") else { print("Failed to get TransferUtility instance") return } // 3. Read audio file data (replace image-specific logic) guard let audioData = try? Data(contentsOf: fileURL) else { print("Failed to load audio file data") return } let fileExtension = fileURL.pathExtension.lowercased() let remoteName = generateRandomStringWithLength(length: 12) + "." + fileExtension let s3BucketName = "testingimageupload" let s3Key = "private/Abhay/" + remoteName // 4. Set correct Content-Type for audio (critical for S3 recognition) var contentType = "audio/mpeg" // Default for MP3 switch fileExtension { case "wav": contentType = "audio/wav" case "aac": contentType = "audio/aac" case "m4a": contentType = "audio/mp4" default: break } // 5. Configure upload expression let expression = AWSS3TransferUtilityUploadExpression() expression.setValue("public-read", forRequestHeader: "x-amz-acl") expression.progressBlock = { (task, progress) in DispatchQueue.main.async { print("Upload progress: \(String(format: "%.1f", progress.fractionCompleted * 100))%") // Update your UI progress bar here } } // 6. Completion handler let completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock = { (task, error) in DispatchQueue.main.async { if let error = error { print("Upload failed: \(error.localizedDescription)") return } print("Audio upload succeeded!") // Get the public URL of the uploaded file if let baseURL = AWSS3.default().configuration.endpoint.url { let publicURL = baseURL.appendingPathComponent(s3BucketName).appendingPathComponent(s3Key) print("Audio URL: \(publicURL.absoluteString ?? "N/A")") } } } // 7. Execute upload transferUtility.uploadData(audioData, bucket: s3BucketName, key: s3Key, contentType: contentType, expression: expression, completionHandler: completionHandler) .continueWith { task in if let error = task.error { print("Transfer task error: \(error.localizedDescription)") } return nil } } // Keep your existing random string generator func generateRandomStringWithLength(length: Int) -> String { let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" return String((0..<length).map{ _ in letters.randomElement()! }) }
Step 4: Final Checks
- Confirm your S3 bucket is hosted in the
us-east-2region (match your code'sregionType). If your bucket is in another region, update the region value accordingly. - Ensure your device has a stable internet connection (AWS SDK errors can sometimes mask network issues).
- For iOS 14+, make sure your
Info.plistdoesn't block HTTPS requests to AWS (AWS uses HTTPS by default, so this should only be an issue if you're using a custom endpoint).
内容的提问来源于stack exchange,提问作者Mobile Dev

