Closed Aviru closed 6 years ago
Hello,
Could you please explain the use-case of why you want to do the multipart upload manually?
We currently have in-built support for this S3TransferUtility
and you can use the multipart upload API to achieve this.
The reason you are getting 403 is that the presigned URL is for put
operation and not multi part upload operation.
Thanks, Rohan
Hi, Thanks for your response. In documentation it has been stated that:-
If you expect your app to perform transfers that take longer than 50 minutes, use AWSS3 instead of AWSS3TransferUtility. AWSS3TransferUtility generates Amazon S3 pre-signed URLs to use for background data transfer. Using Amazon Cognito Identity, you receive AWS temporary credentials. The credentials are valid for up to 60 minutes. At the same time, generated S3 pre-signed URLs cannot last longer than that time. Because of this limitation, the AWSS3TransferUtility enforces 50 minutes transfer timeout, leaving a 10 minute buffer before AWS temporary credentials are regenerated. After 50 minutes, you receive a transfer failure. S3TransferUtility
I am using PUT operation for upload.
func startUploadForPresignedURL (_ presignedURL:URL, chunkURL: URL, md5 : String, MediaName : String, strContentType : String, awsPartNumber: Int)
{
let request = NSMutableURLRequest(url: presignedURL)
request.cachePolicy = .reloadIgnoringLocalCacheData
request.timeoutInterval = Date(timeIntervalSinceNow: 36 * 60 * 60).timeIntervalSinceNow
request.httpMethod = "PUT"
request.setValue("public-read", forHTTPHeaderField: "x-amz-acl")
request.setValue(MediaName, forHTTPHeaderField: "filename")
request.setValue(strContentType, forHTTPHeaderField: "Content-Type")
request.setValue(self.md5File(url: chunkURL), forHTTPHeaderField: "Content-MD5")
let uploadTask = self.session?.uploadTask(with: request as URLRequest, fromFile: chunkURL)
uploadTask?.taskDescription = String(awsPartNumber)
uploadTask?.resume()
}
@rohandubal , any solution please?
I have also tried using Alamofire multipart stream upload. But no luck. The same error is comming. So, any help would be very much helpful.
@Aviru
You should be able to control the expiry limit in the Transfer Utility using the timeoutIntervalForResource
(see code snippet below).
let serviceConfiguration = AWSServiceManager.default().defaultServiceConfiguration
let transferUtilityConfiguration = AWSS3TransferUtilityConfiguration()
//Set the timeoutIntervalForResource parameter (in seconds)
transferUtilityConfigurationWithRetry.timeoutIntervalForResource = 15*60 //15 minutes
AWSS3TransferUtility.register(
with: serviceConfiguration!,
transferUtilityConfiguration: transferUtilityConfiguration,
forKey: "custom-timeout"
)
//Instantiate the transfer utility
let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "custom-timeout")
The 50 minute time limit exists if you use Cognito Identity. However, you can use static credentials to have a much longer time limit ( see https://github.com/aws/aws-sdk-ios/issues/910)
@Aviru I concur with @rohandubal that you should be using the TransferUtility instead of rolling your own implementation.
That said, looking at your code, one thing that jumped out at me was that you are setting the x-amz-acl in the request to upload the part. That header is not allowed for a part ( See https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html for a list of all allowed headers when uploading a part) and is likely causing the server to reject it as an invalid request. The x-amz-acl header should only be included in the createMultiPart request. Remove that header from the part upload and that should resolve the 403 error.
See the code from Line 1315 for how the TransferUtility creates a presigned URL for a part and uploads it using a NSURLSessionUploadTask. https://github.com/aws/aws-sdk-ios/blob/7c6c287f5cf0313ef042d34f18b5f82b27298a30/AWSS3/AWSS3TransferUtility.m#L1315
Look at code starting from line 131 for the details of how the transferUtility looks for certain headers and strips them out of the part upload. https://github.com/aws/aws-sdk-ios/blob/7c6c287f5cf0313ef042d34f18b5f82b27298a30/AWSS3/AWSS3TransferUtility%2BHeaderHelper.m#L131
@cbommas Thanks for your response. You said
I concur with @rohandubal that you should be using the TransferUtility instead of rolling your own implementation.
But I didn't understand what is wrong with my approach. As because AWSTransferUtility doesn't support transfers that take longer than 50 minutes. So, I am using this. I am implementing your solution and let you know asap.
Thanks.
@Aviru
I don't think that there is anything wrong with your approach, it is just a suggestion as the TransferUtility should make it easier for you to do mulitpart uploads.
Regarding the 50 minute limitation, see my earlier post on how you can get around that.
@Aviru
Looks like your problem has been resolved as I haven't heard back. I will go ahead and close out this issue. Please feel free to reopen if you are running into further issues.
@cbommas @Aviru I am beginner in aws can u please help me out how to upload file using multipart in iOS Swift, I have checked out some examples and tutorials but it was not help me out, kindly help me, to achieve this, Thanks in advance
Just in case anyone else sees this: The problem here is is not on the iOS side but the configuration on AWS that needs to be set accordingly so that Content-Type
is accepted (as set by URLSession's upload(:fromFile)
automatically). As of 2023:
It turns out that your region (eu-west-1) supports signature version 2 and 4 and it makes tricky when used with multipart upload and presigned URLs. You can find more information about signature version 4 on link [2] and check regions with supported signature versions on link [3]. I suggest specifying signature version 4 and virtual host for addresing style. Virtual host style address is recommended since it has more benefits than path style address. Please take a look at link [4].
[1] https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html [2] https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html [3] https://docs.aws.amazon.com/general/latest/gr/s3.html#s3-core [4] https://boto3.amazonaws.com/v1/documentation/api/1.9.42/guide/s3.html
To help us solve your problem better, please answer the following list of questions.
What service are you using? AWSS3
In what version of SDK are you facing the problem? AWSS3 (2.6.26)
Is the issue limited to Simulators / Actual Devices? Both Simulators and Actual Devices
Can your problem be resolved if you bump to a higher version of SDK? No
Is this problem related to specific iOS version? No
How are you consuming the SDK? CocoaPods / Carthage / Prebuilt frameworks? CocoaPods
Can you give us steps to reproduce with a minimal, complete, and verifiable example? Please include any specific network conditions that might be required to reproduce the problem.
I am receiving error while uploading multipart data in chunks in S3 bucket using presigned url in Swift. My code is : -
The error is: -
Please help. I have tried different options, but none worked.