使用 Alamofire 和 BOX API 的多部分表单上传

Posted

技术标签:

【中文标题】使用 Alamofire 和 BOX API 的多部分表单上传【英文标题】:Multi-part form upload using Alamofire and BOX API 【发布时间】:2016-10-27 16:27:19 【问题描述】:

我很难让它发挥作用。我正在尝试按照Getting Started section 中的 API 说明将文件上传到 Box

我正在使用 Xcode 8、Swift 3 和 Alamofire 4 框架。我已经用谷歌搜索并搜索了堆栈溢出。我觉得我已经接近了,但是文件上传它仍然无法正常工作。

我不断收到来自 BOX API 的错误消息:

[结果]:成功: 代码 = "bad_request"; “上下文信息”= 错误 = ( message = "'父' 是必需的"; 名字=父母; 原因=“缺少参数”; ); ;

这是我的代码

func testUpload() 


    let endpoint = "https://upload.box.com/api/2.0/files/content"

    let headers: HTTPHeaders = [
        "Authorization": "Bearer \(tempDeveloperToken)"
    ]

    let jsonAttributes = JSON(["name": "test.pdf", "parent": ["id": "11774646649"]])
    let file = PDFService.getPDF(named: "document")            //Returns file as URL

    let paramAttributes = jsonAttributes.stringValue.data(using: String.Encoding.utf8)

    Alamofire.upload(
        multipartFormData:  multipartFormData in
            multipartFormData.append(paramAttributes!, withName: "attributes")
            multipartFormData.append(file, withName: "file")
        ,
        to: endpoint,
        method: .post,
        headers: headers,
        encodingCompletion:  encodingResult in
            switch encodingResult 
            case .success(let upload, _, _):
                upload.responseJSON  response in
                    debugPrint(response)
                
            case .failure(let encodingError):
                print(encodingError)
            
        
    )


我尝试了许多不同的方法来将参数添加到上传中,我缺少什么?

【问题讨论】:

终于想通了,并通过自己的问题回答。请参阅下面的解决方案。 【参考方案1】:

经过多次尝试错误并在这件事上花费数小时看看有什么问题,我终于让它工作了。我没有将参数作为 JSON 字符串传递,而是决定将其保留为指定的文档,但在编码之前手动转义字符串中的每个双引号。您可以在我的解决方案中看到我创建了一个名为 "retest" 的新变量,它是替换旧变量 "jsonAttributes" 的修复程序。我不知道是否有更好的方法来编写此解决方案,但这对我有用。

func testUpload() 

    let endpoint = "https://upload.box.com/api/2.0/files/content"

    let headers: HTTPHeaders = [
        "Authorization": "Bearer \(tempDeveloperToken)"
    ]

    //let jsonAttributes = JSON(["name": "test.pdf", "parent": ["id": "11774646649"]])
    let retest = "\"name\":\"test.pdf\", \"parent\":\"id\":\"11774646649\""
    let paramAttributes = retest.data(using: String.Encoding.utf8) //jsonAttributes.stringValue.data(using: String.Encoding.utf8)

    let file = PDFService.getPDF(named: "document")            //Returns file as URL


    Alamofire.upload(
        multipartFormData:  multipartFormData in
            multipartFormData.append(paramAttributes!, withName: "attributes")
            multipartFormData.append(file, withName: "file")
        ,
        to: endpoint,
        method: .post,
        headers: headers,
        encodingCompletion:  encodingResult in
            switch encodingResult 
            case .success(let upload, _, _):
                upload.responseJSON  response in
                    debugPrint(response)
                
            case .failure(let encodingError):
                print(encodingError)
            
        
    )


【讨论】:

【参考方案2】:

多部分表单看起来正确。您可以尝试删除parent 标头。它不需要在那里。

【讨论】:

哎呀,父标题是我忘记删除的东西。我已经删除了它,但似乎不是问题。这让我很烦恼,根据我的所有研究,我的代码看起来是正确的。不确定 API 为何拒绝它。 明白了。请使用Fiddler 之类的内容捕获请求的 HTTP 跟踪,以便我们可以看到网络上发生了什么。您的代码确实不错,但可能存在不明显的序列化问题。 在尽我所能解决这个问题之后,我终于让它工作了。解决方案非常令人惊讶,但它奏效了。很快就会发布解决方案。 好的,很高兴你没有被困住。您的解决方案表明毕竟存在某种序列化问题。如果是我,我会花时间通过 a) 检查 JSON 的字符串化版本,或者 b) 查看请求的 HTTP 跟踪来找出问题的根源。您最终可能需要使用内置的 JSON 序列化程序... 是的,我应该做一些根本原因分析。每次我需要使用参数进行 API 调用时,我都不想手动转义引号。即使它是“安全的”,因为我什至在编译之前就可以看到它,有点痛苦。不过,感谢您的投入,帮助铺平了道路。

以上是关于使用 Alamofire 和 BOX API 的多部分表单上传的主要内容,如果未能解决你的问题,请参考以下文章

通过 API 将带有 Alamofire 的 STL 文件上传到 Octoprint

使用 Alamofire 的多部分 POST

使用 alamofire 的多部分/表单数据

如何处理Alamofire中的多部分/相关数据?

带有 JSON 参数的多部分数据 Alamofire

使用 Alamofire 从 API 获取响应