使用AlamoFire和预签名URL将图像上传到S3 Bucket时出现问题



我的应用程序上传到S3的方法是向我的PHP后端发送一个get请求,以生成一个预签名的URL。我知道后端设置正确,因为运行以下命令成功地将图像上传到S3存储桶:

curl -v -H "Content-Type: image/jpeg" -T ./test.jpeg '<presignedURL>'

然而,我在尝试用Swift上传图片时遇到了问题。这是我目前的实现(请忽略垃圾,硬编码,无错误检查(:

后端

<?php
require '../vendor/autoload.php';
use AwsS3S3Client;
use AwsExceptionAwsException;
$response = array();
$client = S3Client::factory(array(
'profile' => 'default',
'version' => 'latest',
'region' => 'us-east-2',
'signature' => 'v4'
));
$command = $client->getCommand('PutObject', array(
'Bucket'      => 'test',
'Key'         => 'test.jpeg',
'ContentType' => 'image/jpeg',
'Body'        => ''
));
$signedUrl = $command->createPresignedUrl('+5 minutes');
$response['error'] = false;
$response['url'] = $signedUrl;
echo json_encode($response);

Swift代码

import Foundation
import Alamofire
let getTokenURL = "http://192.168.1.59:8000/v1/upload.php"
func submitImage(image: UIImage, completion: @escaping (NSDictionary) -> Void) {

AF.request(getTokenURL, method: .get).responseJSON { response in

switch response.result {
case.success(let value):
let jsonData = value as! NSDictionary
let url = jsonData.value(forKey: "url") as! String

performUpload(image: image, postURL: url)

case.failure(_):
let error_msg: NSDictionary = [
"error" : true,
"message" : "Unknown error occurred. Please try again",
]

//completion(error_msg)
}
}

}
func performUpload(image: UIImage, postURL: String) {
let imageData = image.jpegData(compressionQuality: 0.50)!

AF.upload(imageData, to: postURL, headers: ["Content-Type":"image/jpeg"])    //likely the culprit line
}

目前,URL是从submitImage((中的get请求返回的,并调用performUpload((,这使得罪魁祸首(很可能(成为我Swift代码段的最后一个时间。在阅读文档时,我很难弄清楚我应该做什么,因为AlamoFire已经改变了它们的语法,所以大多数关于这个主题的指南都已经过时了。如有任何帮助,我们将不胜感激。非常感谢。

编辑:我已经调整了performUpload((函数。它现在将数据上传到s3 bucket,但无法打开图像。我怀疑这是因为请求中的标头不正确。通过调试,我可以看出Content-Type头是";多部分/形式数据";不管怎样,所以我不确定这种方法是否可行:

struct HTTPBinResponse: Decodable { let url: String }
func performUpload(image: UIImage, postURL: String) {
let imageData = image.jpegData(compressionQuality: 0.50)!

AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imageData, withName: "file", mimeType: "image/jpeg")
}, to: postURL, method: .put, headers: ["Content-Type":"image/jpeg"]).responseDecodable(of: HTTPBinResponse.self) { response in
debugPrint(response)
}  
}

对于未来的读者,这里的关键是添加method: .put!这个问题其他的都很好。

此外,我发现您必须使用空的内容类型标头。S3很奇怪。

AF.upload(imageData, to: postURL, method: .put, headers: ["Content-Type": ""])

最新更新