我正在尝试在Swift中上传带有参数的图像。当我尝试此代码时,我可以获取参数,但不能获取图像
uploadFileToUrl(fotiño:UIImage){ var foto = UIImage(data: UIImageJPEGRepresentation(fotiño, 0.2)) var request = NSMutableURLRequest(URL:NSURL(string: "URL")) request.HTTPMethod = "POST" var bodyData = "id_user="PARAMETERS&ETC"" request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding); request.HTTPBody = NSData.dataWithData(UIImagePNGRepresentation(foto)) println("miraqui \(request.debugDescription)") var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil var HTTPError: NSError? = nil var JSONError: NSError? = nil var dataVal: NSData? = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error: &HTTPError) if ((dataVal != nil) && (HTTPError == nil)) { var jsonResult = NSJSONSerialization.JSONObjectWithData(dataVal!, options: NSJSONReadingOptions.MutableContainers, error: &JSONError) if (JSONError != nil) { println("Bad JSON") } else { println("Synchronous\(jsonResult)") } } else if (HTTPError != nil) { println("Request failed") } else { println("No Data returned") } }
编辑2:
我认为保存的UIImage的路径存在一些问题,因为php告诉我该文件已经存在,这是因为我将其发送为空白
func createRequest (#userid: String, disco: String, id_disco: String, pub: String, foto: UIImage) -> NSURLRequest { let param = [ "id_user" : userid, "name_discoteca" : disco, "id_discoteca" : id_disco, "ispublic" : pub] // build your dictionary however appropriate let boundary = generateBoundaryString() let url = NSURL(string: "http....") let request = NSMutableURLRequest(URL: url) request.HTTPMethod = "POST" request.timeoutInterval = 60 request.HTTPShouldHandleCookies = false request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") var imagesaver = ImageSaver() var image = foto // However you create/get a UIImage let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String let destinationPath = documentsPath.stringByAppendingPathComponent("VipKing.jpg") UIImageJPEGRepresentation(image,1.0).writeToFile(destinationPath, atomically: true) self.saveImage(foto, withFileName: "asdasd22.jpg") var path = self.documentsPathForFileName("asdasd22.jpg") self.ViewImage.image = self.loadImageWithFileName("asdasd22.jpg") // let path1 = NSBundle.mainBundle().pathForResource("asdasd22", ofType: "jpg", inDirectory: path) as String! **//path1 always crash** println(param.debugDescription) println(path.debugDescription) println(boundary.debugDescription) request.HTTPBody = createBodyWithParameters(param, filePathKey: "asdasd22.jpg", paths: [path], boundary: boundary) println(request.debugDescription) return request }
在下面的评论中,您告知我们您正在使用$_FILES语法来检索文件。这意味着您要创建一个multipart/form-data请求。该过程基本上是:
$_FILES
multipart/form-data
为您的multipart/form-data请求指定边界。
指定Content-Type请求的一个,以指定该请求multipart/form-data及其边界。
Content-Type
创建请求正文,将各个组成部分分开(每个发布的值以及每个上传之间的值)。
有关更多详细信息,请参见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 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)\r\n") body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n") body.append("\(value)\r\n") } for url in urls { let filename = url.lastPathComponent let data = try Data(contentsOf: url) let mimetype = mimeType(for: filename) 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 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 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,您将执行以下操作:
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()