我在Swift中使用预签名的URL在S3 bucket中上传多部分数据时收到错误。
我的代码是:-
func AWSS3UploadMultipartData(data: Data, strVideoName : String, strContentType: String , _ completion: @escaping s3CompletionHandler)
{
let multipartRequest = AWSS3CreateMultipartUploadRequest()
multipartRequest?.key = strVideoName
multipartRequest?.bucket = S3BucketName
multipartRequest?.contentType = strContentType
let awsService = AWSS3.default()
awsService.createMultipartUpload(multipartRequest!) { (multipartUploadOutput, error) in
self.multipartUploadId = multipartUploadOutput?.uploadId
self.completedPartsInfo = AWSS3CompletedMultipartUpload()
self.uploadAllParts()
}
}
func uploadAllParts ()
{
repeat {
// get the length of the chunk
let thisChunkSize = xxxxx;
// get the chunk data
let chunk = xxxxxx
//saving the file to Documents Directory in chunkURL
self.uploadAWSPart(uploadDict: dict, fileURL: chunkURL!, mediaName : fileName,
awsPartNumber: offset)
offset += thisChunkSize;
} while (offset < length);
}
func uploadAWSPart(uploadDict : [String : Any], fileURL : URL, mediaName : String, awsPartNumber : Int)
{
let getPreSignedURLRequest = AWSS3GetPreSignedURLRequest()
getPreSignedURLRequest.bucket = S3BucketName
getPreSignedURLRequest.key = mediaName
getPreSignedURLRequest.httpMethod = AWSHTTPMethod.PUT;
getPreSignedURLRequest.expires = Date(timeIntervalSinceNow: 36 * 60 * 60);
getPreSignedURLRequest.contentType = contentType
getPreSignedURLRequest.setValue(self.multipartUploadId, forRequestParameter: "uploadId")
getPreSignedURLRequest.setValue(String(awsPartNumber), forRequestParameter: "partNumber")
let MD5 = self.md5File(url: fileURL)
getPreSignedURLRequest.contentMD5 = MD5
let presignedTask =
AWSS3PreSignedURLBuilder.default().getPreSignedURL(getPreSignedURLRequest)
presignedTask.continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask!) -> AnyObject! in
if let presignedURL = task.result
{
///This is the response of presignedURL:-
*******************************************************
https://bucketName.s3-ap-south-
1.amazonaws.com/c9e407127756360d54b85a469b728e0d_1534190164.75355.mp4?
X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-
Credential=AKIAIBZJLCO6SJCZZ7YQ%2F20180813%2Fap-south-
1%2Fs3%2Faws4_request&X-Amz-Date=20180813T195604Z&X-Amz-
Expires=129599&X-Amz-SignedHeaders=content-md5%3Bcontent-
type%3Bhost&uploadId=RSjis.pARzI3IPESBYvxWhcY5ta_ybURr7fnUK4fKBVTTS9cMjyVfG4nmJVAu
O.cQ.K7mSAPpLzLwW7CElIUyFaXnMmCTrr7A2p7r1KG79Q-&partNumber=0&X-Amz-
Signature=f2d555fd64f80e1ba86c8ed0b0eb63a1b184304fcbfde6a91198163df2a67900
*********************************************************
self.startUploadForPresignedURL (presignedURL as URL, chunkURL: fileURL, md5 :
MD5!, MediaName : mediaName, strContentType : contentType, awsPartNumber:
awsPartNumber)
}
return nil
})
}
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()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
print("\(#function)")
if (error != nil) {
print("didCompleteWithError error: \(String(describing: error?.localizedDescription))")
}
else {
print("didCompleteWithError success: \(String(describing: task.response))")
}
}
字符串
错误为:-
<NSHTTPURLResponse: 0x1c4432b60> { URL: https://bucketName.s3-ap-Region.amazonaws.com/xxxxx.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIBZJLCO6SJCZZ7YQ%2F20180812%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20180812T190423Z&X-Amz-Expires=129599&X-Amz-SignedHeaders=content-md5%3Bcontent-type%3Bhost&uploadId=rtRmP_xSnCVBURpnAnUFSbN5JLy9h11yDyDxtrTmMc9oAFMfIi95hX82bbupk497uIoHtC5tYXezK2fLcHb7fh_aR1win8eiAYCcKakmxvo-&partNumber=17825792&X-Amz-Signature=39d31e9f41371242099164702d329d8e81e6f4b16fabba0ed29507ceabc05130 } { Status Code: 403, Headers {
Connection = (
close
);
"Content-Type" = (
"application/xml"
);
Date = (
"Sun, 12 Aug 2018 19:04:30 GMT"
);
Server = (
AmazonS3
);
"Transfer-Encoding" = (
Identity
);
"x-amz-id-2" = (
"0bmVCpzxQZRVYUSeEKIMrxq0rMd9Ts5eYne7timdoH++ThvvNJo+Wjq9Jhckx/AP1fNiaPhVhqQ="
);
"x-amz-request-id" = (
C171A1AE06D092EF
);
} })
型
我已经尝试了不同的选项,但都没有工作.我也尝试了使用Alamofire多部分流上传,但同样的错误是coming.我也发布了这个问题在github的aws-sdk-ios,但他们也没有适当的答案到现在.任何帮助将不胜感激.
3条答案
按热度按时间lmvvr0a81#
您应该考虑使用AWS移动的iOS SDK中提供的TransferUtility,而不是滚动自己的实现来执行多部分上传。
也就是说,看看你的代码,有一件事让我很吃惊,那就是你在上传部分的请求中设置了x-amz-acl。对于一个部分来说,这个头是不允许的(请参阅https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html,了解上传部件时允许的所有头的列表),并可能导致服务器将其作为无效请求拒绝。acl标头应该只包含在HTTP MultiPart请求中。从部件上传中删除该标头,这应该可以解决403错误。
请参阅第1315行的代码(https://github.com/aws/aws-sdk-ios/blob/7 c6 c287 f5 cf 0313 ef 042 d34 f18 b5 f82 b27298 a30/AWSS 3/AWSS3TransferUtility.m#L1315),了解TransferUtility如何为部件创建预签名的URL并使用NSURLSessionDataTask上传。
另外,请查看从第131行开始的代码(https://github.com/aws/aws-sdk-ios/blob/7 c6 c287 f5 cf 0313 ef 042 d34 f18 b5 f82 b27298 a30/AWSS 3/AWSS 3 TransferUtility如何查找某些头部并将其从部件上传中剥离出来的详细信息。
n8ghc7c12#
所以我使用AWSS3GetPreSignedURLRequest()来获取一个PUT presignedURL,并使用URLSession.upload来使用它,一切都很好。使用Alamofire.upload使用相同的参数,总是得到一个签名错误。想使用AWS upload之外的东西,因为你不能用它来控制重试或超时。
vyswwuz23#
以防其他人看到这一点:这里的问题不是在iOS端,而是需要相应地设置AWS上的配置,以便接受
Content-Type
(由URLSession的upload(:fromFile)
自动设置)。截至2023:原来你所在的地区(eu-west-1)支持签名版本2和4,当与多部分上传和预签名的URL一起使用时,它会变得很棘手。您可以在链接[2]上找到有关签名版本4的更多信息,并在链接[3]上检查支持签名版本的区域。我建议指定签名版本4和虚拟主机作为地址样式。建议使用虚拟主机样式地址,因为它比路径样式地址有更多好处。请看看链接[4]。
[1][https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html](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](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](https://boto3.amazonaws.com/v1/documentation/api/1.9.42/guide/s3.html)的