在没有 SDK 的情况下将文件上传到 Quickblox,最好使用 Alamofire
Upload file to Quickblox without SDK, ideally with Alamofire
我正在尝试从用 Swift 编写的 OS X 项目将 sqlite 文件上传到 Quickblox 服务器。我已经在 iOS 上使用 Quickblox iOS SDK 解决了这个问题:
let file = QBCOFile()
file.name = "ThisFileName"
file.contentType = "sqlite"
let theData = NSData(contentsOfFile: originalPath)
file.data = theData
QBRequest.uploadFile(file, className: "MyClassName", objectID: cusObjID, fileFieldName: "FieldName", successBlock: {(response:QBResponse,fileUploadInfo:QBCOFileUploadInfo?) in
}, statusBlock: nil, errorBlock: {(response:QBResponse) in
showError()
})
使用 OS X,我一直在使用 Alamofire 并且收到了其他工作请求,但不是这个。他们的 API 页面 (https://quickblox.com/developers/Custom_Objects#Upload.2FUpdate_file) 上的请求描述是这样的:
curl -X POST -H "QB-Token: e7cde5f7f5b93f3fa5ac72a281777cbf0f908374" -F "field_name=avatar" -F 'file=@"ava.jpg"' https://api.quickblox.com/data/<Class_name>/<record_id>/file.json
此描述与其他描述之间的一个主要区别是我不确定如何处理的“-F”。这是我迄今为止尝试过的代码的一种变体:
Alamofire.upload(Method.POST, "https://api.quickblox.com/data/MyClassName/\(cusObjID)/file.json",
headers: ["QB-Token":realToken],
multipartFormData: { multipartFormData in
if let valData = "FieldName".dataUsingEncoding(NSUTF8StringEncoding) {
multipartFormData.appendBodyPart(data: valData, name: "field_name")
}
multipartFormData.appendBodyPart(data: theData, name: "ThisFileName", fileName: "ThisFileName.sqlite", mimeType: "multipart/form-data")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .Failure(let encodingError):
print(encodingError)
}
}
我知道令牌和自定义 object ID (cusObjID) 有效,因为我在其他请求中使用过它们。我在 "appendBodyPart" 部分尝试了很多变体,他们都给了我这个结果:
[Result]: SUCCESS: {
errors = (
"Wrong arguments"
);
}
并且响应包含
Status = "404 Not Found";
我在 Whosebug 上看到了一些答案,提示 Alamofire 可能不适用于此类上传,所以如果有其他方法可以做到这一点,那也很好。真的,我正在寻找使用 iOS Quickblox SDK 完成我在 iOS 上所做的任何方法。
更新
使用这个问题的最后一个答案的编辑 (Uploading file with parameters using Alamofire),我已经能够在文件上传时更新进度
.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
Swift.print("\(totalBytesWritten) / \(totalBytesExpectedToWrite)")
}
但我仍然遇到同样的错误。顺便说一下,这就是我的请求 header 从成功的 iOS 版本来看的样子:
Request headers: {
"Accept-Language" = "en-US;q=1";
"Content-Length" = 6488309;
"Content-Type" = "multipart/form-data; boundary=Boundary+88AB02F344BB7C4E";
"QB-Token" = b6f06b9e6e45c839aecc89019add6bd1;
"User-Agent" = "App Name/2.1 (iPhone; iOS 9.3; Scale/2.00)";
}
好吧,我在 Alamofire 上苦苦挣扎了一段时间,但从来没有让它做我想做的事。我切换到另一个框架 SwiftHTTP (https://github.com/daltoniam/SwiftHTTP),它能够毫不费力地完成任务(与使用 Quickblox iOS SDK 一样容易):
do {
let opt = try HTTP.POST("https://api.quickblox.com/data/MyClassName/\(cusObjID)/file.json", parameters: ["field_name": "FieldName", "file": Upload(fileUrl: url)], headers: ["QB-Token":realToken])
opt.start { response in
if response.error == nil {
} else {
showError()
}
}
} catch {
showError()
}
我正在尝试从用 Swift 编写的 OS X 项目将 sqlite 文件上传到 Quickblox 服务器。我已经在 iOS 上使用 Quickblox iOS SDK 解决了这个问题:
let file = QBCOFile()
file.name = "ThisFileName"
file.contentType = "sqlite"
let theData = NSData(contentsOfFile: originalPath)
file.data = theData
QBRequest.uploadFile(file, className: "MyClassName", objectID: cusObjID, fileFieldName: "FieldName", successBlock: {(response:QBResponse,fileUploadInfo:QBCOFileUploadInfo?) in
}, statusBlock: nil, errorBlock: {(response:QBResponse) in
showError()
})
使用 OS X,我一直在使用 Alamofire 并且收到了其他工作请求,但不是这个。他们的 API 页面 (https://quickblox.com/developers/Custom_Objects#Upload.2FUpdate_file) 上的请求描述是这样的:
curl -X POST -H "QB-Token: e7cde5f7f5b93f3fa5ac72a281777cbf0f908374" -F "field_name=avatar" -F 'file=@"ava.jpg"' https://api.quickblox.com/data/<Class_name>/<record_id>/file.json
此描述与其他描述之间的一个主要区别是我不确定如何处理的“-F”。这是我迄今为止尝试过的代码的一种变体:
Alamofire.upload(Method.POST, "https://api.quickblox.com/data/MyClassName/\(cusObjID)/file.json",
headers: ["QB-Token":realToken],
multipartFormData: { multipartFormData in
if let valData = "FieldName".dataUsingEncoding(NSUTF8StringEncoding) {
multipartFormData.appendBodyPart(data: valData, name: "field_name")
}
multipartFormData.appendBodyPart(data: theData, name: "ThisFileName", fileName: "ThisFileName.sqlite", mimeType: "multipart/form-data")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .Failure(let encodingError):
print(encodingError)
}
}
我知道令牌和自定义 object ID (cusObjID) 有效,因为我在其他请求中使用过它们。我在 "appendBodyPart" 部分尝试了很多变体,他们都给了我这个结果:
[Result]: SUCCESS: {
errors = (
"Wrong arguments"
);
}
并且响应包含
Status = "404 Not Found";
我在 Whosebug 上看到了一些答案,提示 Alamofire 可能不适用于此类上传,所以如果有其他方法可以做到这一点,那也很好。真的,我正在寻找使用 iOS Quickblox SDK 完成我在 iOS 上所做的任何方法。
更新
使用这个问题的最后一个答案的编辑 (Uploading file with parameters using Alamofire),我已经能够在文件上传时更新进度
.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
Swift.print("\(totalBytesWritten) / \(totalBytesExpectedToWrite)")
}
但我仍然遇到同样的错误。顺便说一下,这就是我的请求 header 从成功的 iOS 版本来看的样子:
Request headers: {
"Accept-Language" = "en-US;q=1";
"Content-Length" = 6488309;
"Content-Type" = "multipart/form-data; boundary=Boundary+88AB02F344BB7C4E";
"QB-Token" = b6f06b9e6e45c839aecc89019add6bd1;
"User-Agent" = "App Name/2.1 (iPhone; iOS 9.3; Scale/2.00)";
}
好吧,我在 Alamofire 上苦苦挣扎了一段时间,但从来没有让它做我想做的事。我切换到另一个框架 SwiftHTTP (https://github.com/daltoniam/SwiftHTTP),它能够毫不费力地完成任务(与使用 Quickblox iOS SDK 一样容易):
do {
let opt = try HTTP.POST("https://api.quickblox.com/data/MyClassName/\(cusObjID)/file.json", parameters: ["field_name": "FieldName", "file": Upload(fileUrl: url)], headers: ["QB-Token":realToken])
opt.start { response in
if response.error == nil {
} else {
showError()
}
}
} catch {
showError()
}