GoogleDrive + Alamofire:上传带有属性的文件

Posted

技术标签:

【中文标题】GoogleDrive + Alamofire:上传带有属性的文件【英文标题】:GoogleDrive + Alamofire: Uploading a file with properties 【发布时间】:2016-07-19 05:33:24 【问题描述】:

我正在尝试通过 Swift 2/Alamofire 将文件 + 参数上传到 Google Drive。在下面的代码中,我更改了以下行:

"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"

到以下:

"https://www.googleapis.com/upload/drive/v3/files"

文件上传到谷歌没有名称。否则,文件上传会失败并使用相同的通用代码:

Error Domain=com.alamofire.error Code=-6003 "Response status code was unacceptable: 400" UserInfo=NSLocalizedFailureReason=Response status code was unacceptable: 400

我希望能够上传带有名称和其他参数的文件。我知道我正在以某种方式破坏分段上传,但我不知道我做错了什么。

  func postBinaryToGdriveSimple (token: String, callback: Bool -> Void)
var returnedId : String!
let path = NSBundle.mainBundle().pathForResource("drawing", ofType: "bin")

let bindata: NSData = NSData(contentsOfURL: NSURL(fileURLWithPath: path!))!
let parameters : [String: String] = ["title":"SomeFileName"]
let headers = ["Authorization": "Bearer \(token)"]
upload(
  .POST,
  "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
  headers: headers,

  multipartFormData:  multipartFormData in
    // append file parameters to request
    for (key, value) in parameters 
      multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
    
    // append binary file to request
    multipartFormData.appendBodyPart(data: bindata, name: "upload", fileName: "drawing.bin", mimeType: "application/octet-stream")

  ,
  encodingCompletion:  encodingResult in
    switch encodingResult 
    case .Success(let upload, _, _):
      upload.progress  bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
        dispatch_async(dispatch_get_main_queue()) 
          let percent = (Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
          //progress(percent: percent)
          print ("................\(percent)")
        
      
      upload.validate()
      upload.responseJSON  response in
        switch response.result 
        case .Success(let data):
          print(response)
          print("Validation Successful")

          let json = JSON(data)
          returnedId = json[("id")].stringValue
          print("......id for uploaded file is \(returnedId)")

          callback(true)
        case .Failure(let error):
          print(error)
          print("Validation Bad")
          callback(false)
        


      
    case .Failure(_):
      callback(false)
    
)
 // end of postBinaryToGdriveSimple

我想知道 Alamofire 创建 Google Drive 不喜欢的多部分请求的方式是否存在某些问题。从 google api 站点来看,请求似乎需要具有某些 Alamofire 可能不会创建的参数,例如 Content-length 和边界设置...

POST /upload/drive/v3/files?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body

--foo_bar_baz
Content-Type: application/json; charset=UTF-8


 "name": "My File"


--foo_bar_baz
Content-Type: image/jpeg

JPEG data
--foo_bar_baz--

如果是这样,解决方法是什么?

【问题讨论】:

【参考方案1】:

仔细检查 Google Drive 的 API 文档。

参数的关键字段似乎是“名称”(而不是“标题”)。

如果您想要附加的自定义文件属性,仅限于单个应用程序,请在 json 中添加“appProperties”:

“应用程序属性”: “标题”:“随便”

【讨论】:

非常感谢您查看我的问题。您对我对“名称”参数的疏忽是正确的……但是,这并没有解决问题。我更新了我的问题以包含有关来自 GoogleDrive API 文档的多部分请求的简介……Alamofire 是否有可能没有发送发出请求所需的所有信息?如果有,如何解决? 哦,好吧,尝试注释掉 multipartFormData 闭包中的 for in 循环,看看如果添加: multipartFormData.appendBodyPart(data:"'name':'FILE_NAME'".dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)!, name :"name", mimeType: "application/json") 顺便说一句,边界由 alamofire 设置,当您“附加身体部位”时。 AF 方法应该为 POST 自行提取 Content-Length,并且 mimeType 参数为请求的该部分设置 Content-Type。 github.com/Alamofire/Alamofire/blob/master/Source/… 太棒了!再一次,你通过了。我喜欢这个答案的简单性。 multipartFormData.appendBodyPart(data:"'name':'FILE_NAME'".dataUsingEncoding(N‌​SUTF8StringEncoding, allowLossyConversion: false)!, name :"name", mimeType: "application/json") 解决了我的问题。非常感谢! 酷。所以只是添加一些颜色......在 multipartFormData.appendBodyPart(data:"DATA_TO_ENCODE" 参数的主引号内添加的任何内容都已编码。请注意,这些主引号在 Swift 中定义了一个字符串并且不包含在编码中,只是就像您的参数字典变量一样。JSON 需要 、: 和 "" 字符。我使用单引号以方便回答,但 JSON 标准是双引号,因此从技术上讲您应该使用 \" (转义双引号在我有 ' 单引号字符)。然后通过 mimeType 将 Content-Type 设置为 application/json。

以上是关于GoogleDrive + Alamofire:上传带有属性的文件的主要内容,如果未能解决你的问题,请参考以下文章

GoogleDrive 7 天刷新令牌

colab使用自己的数据

在操场上使用 Alamofire 发出 http 请求的延迟

使用 alamofire 在 Swift 上解析 Json

关于在 Xcode 上导入 Alamofire,我是不是遗漏了啥?

Alamofire 的 Session timeOutInterval 和 cachePolicy 设置未反映在 URLRequest 上