Ответ 1
В своем комментарии ниже вы сообщаете нам, что используете синтаксис $_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 created
func 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 path1 = Bundle.main.path(forResource: "image1", ofType: "png")!
request.httpBody = try createBody(with: parameters, filePathKey: "file", paths: [path1], 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 paths: The optional array of file paths 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, paths: [String], boundary: String) throws -> Data {
var body = Data()
if parameters != nil {
for (key, value) in parameters! {
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
for path in paths {
let url = URL(fileURLWithPath: path)
let filename = url.lastPathComponent
let data = try Data(contentsOf: url)
let mimetype = mimeType(for: path)
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(filePathKey)\"; filename=\"\(filename)\"\r\n")
body.append("Content-Type: \(mimetype)\r\n\r\n")
body.append(data)
body.append("\r\n")
}
body.append("--\(boundary)--\r\n")
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 url = URL(fileURLWithPath: path)
let pathExtension = url.pathExtension
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
return mimetype as String
}
}
return "application/octet-stream"
}
С:
extension Data {
/// Append string to Data
///
/// Rather than littering my code 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: URLRequest
do {
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()
Для передач Swift 2 см. Предыдущую редакцию этого ответа.