我的应用程序上传到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": ""])