【问题标题】:Problem Uploading Images to S3 Bucket Using AlamoFire and Presigned URL使用 AlamoFire 和预签名 URL 将图像上传到 S3 存储桶时出现问题
【发布时间】: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”作为参数解决了它

标签: php ios swift amazon-s3 alamofire


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2021-09-09
    • 2022-10-05
    • 1970-01-01
    • 2020-05-15
    • 2019-01-30
    • 2016-03-18
    • 2015-08-26
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多