通过 SWIFT 中的 POST 方法上传名称为 .XML 的文件

Upload an .XML file with a name via POST method in SWIFT

作为 HTTP 服务器请求的一部分,我需要在包含查询信息的 POST 请求中上传一个 .XML 文件。然而,简单地使用 URLSession.shared.uploadTask(with:, fromFile:) 似乎不起作用。像下面这样:

func reportRequest(url: URL) -> Void {
    let fileURL: URL = URL(fileURLWithPath: ".../search_xml.xml")
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "POST"
    urlRequest.setValue(authToken, forHTTPHeaderField: "authorization")
    let task = URLSession.shared.uploadTask(with: urlRequest, fromFile: fileURL) {data, response, error in
        print(String(data: data!, encoding: .utf8)!)
        print(response)
    }
    task.resume()

我在 Python 上使用 requests 模块中的 files 参数,并在其中传递字典像下面这样:

headers = {'authorization': authToken, }
files = {'xmlRequest': open('.../search.xml', 'rb')}
response = requests.post(url, headers=headers, files=files)

我还在 RestMan(管理 REST API 的浏览器扩展)中通过在正文中添加 表单数据 实现了这一点, “xmlRequest”作为键并选择 .XML 文件作为值。

在SWIFT中似乎我必须自己构建请求主体,但我对此知之甚少,而且我找到的教程主要是关于上传图片的,这可能有所不同。

提前致谢!

这是一个上传文件的通用示例。

let headers = [
  "content-type": "multipart/form-data;",
  "authorization": "authToken",
]

let parameters = [
  [
    "name": "xmlfile",
    "fileName": "search_xml.xml"
  ]
]

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://example.com/fileupload")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()