使用 AlamoFire 和预签名 URL 将图像上传到 S3 存储桶时出现问题
Posted
技术标签:
【中文标题】使用 AlamoFire 和预签名 URL 将图像上传到 S3 存储桶时出现问题【英文标题】:Problem Uploading Images to S3 Bucket Using AlamoFire and Presigned URL 【发布时间】:2021-03-31 02:50:04 【问题描述】:我为我的应用上传到 S3 的方法是向我的 php 后端发送一个获取请求以生成一个预签名 URL。我知道后端设置正确,因为运行以下命令成功将图像上传到 S3 存储桶:
curl -v -H "Content-Type: image/jpeg" -T ./test.jpeg '<presignedURL>'
但是,我在尝试在 Swift 中上传图片时遇到了问题。这是我目前的实现(请忽略垃圾,硬编码,非错误检查):
后端
<?php
require '../vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
$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 存储桶,但是无法打开图像。我怀疑这是因为请求中的标头不正确。从调试中我可以看出 Content-Type 标头无论如何都是“multipart/form-data”,所以我不确定这种方法是否可行:
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)
【问题讨论】:
尝试使用multipart form data 请求发送图像数据并查看。 @Isuru 请检查我的编辑 请求标头为multipart/form-data
没有任何问题。应该是这样的。从标题中删除"Content-Type":"image/jpeg"
,看看会发生什么。
@Isuru 还是同样的问题
@Isuru 有点尴尬,但在我原来的解决方案中添加“method: .put”作为参数解决了它
【参考方案1】:
对于未来的读者,这里的关键是添加method: .put
!这个问题的其他一切都很好。
我还发现您必须使用空的内容类型标头。 S3 很奇怪。
AF.upload(imageData, to: postURL, method: .put, headers: ["Content-Type": ""])
【讨论】:
以上是关于使用 AlamoFire 和预签名 URL 将图像上传到 S3 存储桶时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 9 问题上使用 Alamofire 上传带有 URL 参数的图像
尝试通过 Alamofire 4.0 上传图像时,类型“ParameterEncoding”没有成员“URL”
Firebase 和 Alamofire Url TableViewCell 图像加载问题 Swift 4