如何使用 swift 从 iOS 设备上传文件(到 REDCap)
Posted
技术标签:
【中文标题】如何使用 swift 从 iOS 设备上传文件(到 REDCap)【英文标题】:How to upload a file (to REDCap) from an iOS device using swift 【发布时间】:2021-12-29 19:18:11 【问题描述】:我正在尝试将保存到应用程序(使用 ResearchKit 构建)中目录的文件上传到服务器(通过 REDCap API)。 REDCap API Playground 建议使用多种语言编写代码,但不建议使用 Obj-C 或 Swift。对于这种情况,我需要使用 Swift,这对我来说是第一次。以下是我尝试的一种方法,不幸的是它不起作用:
func postFileToRedcap (_ fileUrl: URL)
guard let url = URL (string: "https://our_redcap_url.edu/api/") else return
let token = "ABCDEFGHIJK123456789" // unique to REDCap project
let record = "1" // can be set elsewhere
let event = ""
let field = "file_upload_field" // name of field in REDCap
if !fileUrl.pathComponents.isEmpty
let fileName = URL(fileURLWithPath: fileUrl.absoluteString).lastPathComponent
var request = URLRequest.init(url: url)
request.httpMethod = "POST"
// parameters required by REDCap
request.addValue(token, forHTTPHeaderField: "token")
request.addValue(fileName, forHTTPHeaderField: "content")
request.addValue("import", forHTTPHeaderField: "action")
request.addValue(record, forHTTPHeaderField: "record")
request.addValue(field, forHTTPHeaderField: "field")
request.addValue(event, forHTTPHeaderField: "event")
request.addValue("json", forHTTPHeaderField: "returnFormat")
let task = URLSession.shared.uploadTask(
with: request,
fromFile: fileUrl
)
task.resume()
主要问题似乎是参数设置,但我似乎找不到适用于 REDCap 的解决方案。
所有帮助都慷慨地接受了。 提前致谢!
【问题讨论】:
也许从一个参数更少的更简单的 API 调用开始,比如检索服务器版本。然后按自己的方式使用此功能。这是一些软件包开发人员贡献的API trouble shooting vignette。它从与语言无关的部分开始。 【参考方案1】:经过太多时间,我意识到关键是要使用
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
但正是来自 Postman 的代码 sn-ps 使我能够成功构建参数数组和有效负载。我敢肯定,这是一个可以简化的工作版本。
import Foundation
guard let url = URL (string: "https://our_redcap_url.edu/api/") else return
let token = "ABCDEFGHIJK123456789" // unique to REDCap project
let record : = "1" // set elsewhere
let event = ""
let field = "file_upload_field" // name of field in REDCap
let path = "path_of_file_to_be_uploaded"
let repeat_instance : Int = 1
let parameters = [
[
"key": "token",
"value": token,
"type": "text"
],
[
"key": "content",
"value": "file",
"type": "text"
],
[
"key": "action",
"value": "import",
"type": "text"
],
[
"key": "record",
"value": record,
"type": "text"
],
[
"key": "field",
"value": field_name,
"type": "text"
],
[
"key": "event",
"value": event,
"type": "text"
],
[
"key": "repeat_instance",
"value": repeat_instance,
"type": "text"
],
[
"key": "returnFormat",
"value": "json",
"type": "text"
],
[
"key": "file",
"src": path,
"type": "file"
]] as [[String : Any]]
// build payload
let boundary = "Boundary-\(UUID().uuidString)"
var body = ""
for param in parameters
if param["disabled"] == nil
let paramName = param["key"]!
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil
body += "\r\nContent-Type: \(param["contentType"] as! String)"
let paramType = param["type"] as! String
if paramType == "text"
let paramValue = param["value"] as! String
body += "\r\n\r\n\(paramValue)\r\n"
else
let paramSrc = param["src"] as! String
let fileData = try? NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData!, encoding: .utf8)!
body += "; filename=\"\(paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
// create URL request and session
var request = URLRequest(url: url,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) data, response, error in
guard let data = data else
print(String(describing: error))
return
print(String(data: data, encoding: .utf8)!)
task.resume()
【讨论】:
以上是关于如何使用 swift 从 iOS 设备上传文件(到 REDCap)的主要内容,如果未能解决你的问题,请参考以下文章
从设备和云存储服务上传和下载图像或文件(文档、PDF)到 iOS 应用程序
如何将 iOS 应用程序从其他帐户上传到 App-Store?