在下面的评论中,您告知我们您正在使用
$_FILES语法来检索文件。这意味着您要创建一个
multipart/form-data请求。该过程基本上是:
为您的
multipart/form-data
请求指定边界。指定
Content-Type
请求的一个,以指定该请求multipart/form-data
及其边界。创建请求正文,将各个组成部分分开(每个发布的值以及每个上传之间的值)。
有关更多详细信息,请参见RFC 7578。无论如何,在Swift
3和更高版本中,这可能看起来像:
/// Create request////// - parameter userid: The userid to be passed to web service/// - parameter password: The password to be passed to web service/// - parameter email: The email address to be passed to web service////// - returns: The `URLRequest` that was createdfunc createRequest(userid: String, password: String, email: String) throws -> URLRequest { let parameters = [ "user_id" : userid, "email" : email, "password" : password] // build your dictionary however appropriate let boundary = generateBoundaryString() let url = URL(string: "https://example.com/imageupload.php")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("multipart/form-data; boundary=(boundary)", forHTTPHeaderField: "Content-Type") let fileURL = Bundle.main.url(forResource: "image1", withExtension: "png")! request.httpBody = try createBody(with: parameters, filePathKey: "file", urls: [fileURL], boundary: boundary) return request}/// Create body of the `multipart/form-data` request////// - parameter parameters: The optional dictionary containing keys and values to be passed to web service./// - parameter filePathKey: The optional field name to be used when uploading files. If you supply paths, you must supply filePathKey, too./// - parameter urls: The optional array of file URLs of the files to be uploaded./// - parameter boundary: The `multipart/form-data` boundary.////// - returns: The `Data` of the body of the request.private func createBody(with parameters: [String: String]?, filePathKey: String, urls: [URL], boundary: String) throws -> Data { var body = Data() parameters?.forEach { (key, value) in body.append("--(boundary)rn") body.append("Content-Disposition: form-data; name="(key)"rnrn") body.append("(value)rn") } for url in urls { let filename = url.lastPathComponent let data = try Data(contentsOf: url) let mimetype = mimeType(for: filename) body.append("--(boundary)rn") body.append("Content-Disposition: form-data; name="(filePathKey)"; filename="(filename)"rn") body.append("Content-Type: (mimetype)rnrn") body.append(data) body.append("rn") } body.append("--(boundary)--rn") return body}/// Create boundary string for multipart/form-data request////// - returns: The boundary string that consists of "Boundary-" followed by a UUID string.private func generateBoundaryString() -> String { return "Boundary-(UUID().uuidString)"}/// Determine mime type on the basis of extension of a file.////// This requires `import MobileCoreServices`.////// - parameter path: The path of the file for which we are going to determine the mime type.////// - returns: Returns the mime type if successful. Returns `application/octet-stream` if unable to determine mime type.private func mimeType(for path: String) -> String { let pathExtension = URL(fileURLWithPath: path).pathExtension as NSString guard let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, nil)?.takeRetainedValue(), let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() else { return "application/octet-stream" } return mimetype as String}带有:
extension Data { /// Append string to Data /// /// Rather than littering my pre with calls to `data(using: .utf8)` to convert `String` values to `Data`, this wraps it in a nice convenient little extension to Data. This defaults to converting using UTF-8. /// /// - parameter string: The string to be added to the `Data`. mutating func append(_ string: String, using encoding: String.Encoding = .utf8) { if let data = string.data(using: encoding) { append(data) } }}拥有所有这些后,您现在需要提交此请求。我建议这是异步完成的。例如,使用
URLSession,您将执行以下操作:
let request: URLRequestdo { request = try createRequest(userid: userid, password: password, email: email)} catch { print(error) return}let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil else { // handle error here print(error ?? "Unknown error") return } // parse `data` here, then parse it // note, if you want to update the UI, make sure to dispatch that to the main queue, e.g.: // // DispatchQueue.main.async { // // update your UI and model objects here // }}task.resume()


