swiftyjson example ios swift http alamofire

ios - example - swiftyjson alamofire



Enviar parĂ¡metros POST con MultipartFormData usando Alamofire, en iOS Swift (9)

¡En Alamofire 4 es importante agregar los datos del cuerpo antes de agregar los datos del archivo!

let parameters = [String: String]() [...] self.manager.upload( multipartFormData: { multipartFormData in for (key, value) in parameters { multipartFormData.append(value.data(using: .utf8)!, withName: key) } multipartFormData.append(imageData, withName: "user", fileName: "user.jpg", mimeType: "image/jpeg") }, to: path, [...] )

Estoy usando Alamofire, la primera vez. Estoy usando la última versión Alamofire 1.3.1. Quiero enviar una imagen, un video y algunos parámetros POST en una llamada API. Estoy usando datos de formulario multiparte. El módulo mutipart está funcionando. Tengo un problema para enviar parámetros de parámetros POST adicionales. Abajo está mi código. "params" es el diccionario que contiene parámetros adicionales? ¿Cómo puedo agregar estos parámetros POST en la solicitud? Por favor ayuda

var fullUrl :String = Constants.BASE_URL + "/api/CompleteChallenge" var params = [ "authKey": Constants.AuthKey, "idUserChallenge": "16", "comment": "", "photo": imagePath, "video": videoPath, "latitude": "1", "longitude": "1", "location": "india" ] let imagePathUrl = NSURL(fileURLWithPath: imagePath!) let videoPathUrl = NSURL(fileURLWithPath: videoPath!) Alamofire.upload( .POST, URLString: fullUrl, // http://httpbin.org/post multipartFormData: { multipartFormData in multipartFormData.appendBodyPart(fileURL: imagePathUrl!, name: "photo") multipartFormData.appendBodyPart(fileURL: videoPathUrl!, name: "video") }, encodingCompletion: { encodingResult in switch encodingResult { case .Success(let upload, _, _): upload.responseJSON { request, response, JSON, error in } } case .Failure(let encodingError): } } )


Así es como resuelvo mi problema

let parameters = [ "station_id" : "1000", "title": "Murat Akdeniz", "body": "xxxxxx"] let imgData = UIImageJPEGRepresentation(UIImage(named: "1.png")!,1) Alamofire.upload( multipartFormData: { MultipartFormData in // multipartFormData.append(imageData, withName: "user", fileName: "user.jpg", mimeType: "image/jpeg") for (key, value) in parameters { MultipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key) } MultipartFormData.append(UIImageJPEGRepresentation(UIImage(named: "1.png")!, 1)!, withName: "photos[1]", fileName: "swift_file.jpeg", mimeType: "image/jpeg") MultipartFormData.append(UIImageJPEGRepresentation(UIImage(named: "1.png")!, 1)!, withName: "photos[2]", fileName: "swift_file.jpeg", mimeType: "image/jpeg") }, to: "http://platform.twitone.com/station/add-feedback") { (result) in switch result { case .success(let upload, _, _): upload.responseJSON { response in print(response.result.value) } case .failure(let encodingError): break print(encodingError) } }


Bueno, dado que los Datos de formulario multiparte están destinados a ser utilizados para la transmisión de datos binarios (y para texto), creo que es una mala práctica enviar datos codificados a String sobre ellos.

Otra desventaja es la imposibilidad de enviar parámetros más complejos como JSON.

Dicho esto, una mejor opción sería enviar todos los datos en forma binaria, es decir, como datos.

Digamos que necesito enviar estos datos

let name = "Arthur" let userIDs = [1,2,3] let usedAge = 20

... junto con la imagen del usuario:

let image = UIImage(named: "img")!

Para eso convertiría esos datos de texto a JSON y luego a binario junto con la imagen:

//Convert image to binary let data = UIImagePNGRepresentation(image)! //Convert text data to binary let dict: Dictionary<String, Any> = ["name": name, "userIDs": userIDs, "usedAge": usedAge] userData = try? JSONSerialization.data(withJSONObject: dict)

Y luego, finalmente envíelo a través de la solicitud de datos de formulario multiparte:

Alamofire.upload(multipartFormData: { (multiFoormData) in multiFoormData.append(userData, withName: "user") multiFoormData.append(data, withName: "picture", mimeType: "image/png") }, to: url) { (encodingResult) in ... }


Como en Swift 3.x para cargar la imagen con el parámetro, podemos usar el siguiente método de carga de alamofire:

static func uploadImageData(inputUrl:String,parameters:[String:Any],imageName: String,imageFile : UIImage,completion:@escaping(_:Any)->Void) { let imageData = UIImageJPEGRepresentation(imageFile , 0.5) Alamofire.upload(multipartFormData: { (multipartFormData) in multipartFormData.append(imageData!, withName: imageName, fileName: "swift_file/(arc4random_uniform(100)).jpeg", mimeType: "image/jpeg") for key in parameters.keys{ let name = String(key) if let val = parameters[name!] as? String{ multipartFormData.append(val.data(using: .utf8)!, withName: name!) } } }, to:inputUrl) { (result) in switch result { case .success(let upload, _, _): upload.uploadProgress(closure: { (Progress) in }) upload.responseJSON { response in if let JSON = response.result.value { completion(JSON) }else{ completion(nilValue) } } case .failure(let encodingError): completion(nilValue) } } }

Nota: Además, si nuestro parámetro es una matriz de pares de claves, entonces podemos usar

var arrayOfKeyPairs = [[String:Any]]() let json = try? JSONSerialization.data(withJSONObject: arrayOfKeyPairs, options: [.prettyPrinted]) let jsonPresentation = String(data: json!, encoding: .utf8)


Encontré la solución :) finalmente.

Podemos agregar datos en la solicitud como datos multipartform.

Abajo está mi código.

Alamofire.upload( .POST, URLString: fullUrl, // http://httpbin.org/post multipartFormData: { multipartFormData in multipartFormData.appendBodyPart(fileURL: imagePathUrl!, name: "photo") multipartFormData.appendBodyPart(fileURL: videoPathUrl!, name: "video") multipartFormData.appendBodyPart(data: Constants.AuthKey.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"authKey") multipartFormData.appendBodyPart(data: "/(16)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"idUserChallenge") multipartFormData.appendBodyPart(data: "comment".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"comment") multipartFormData.appendBodyPart(data:"/(0.00)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"latitude") multipartFormData.appendBodyPart(data:"/(0.00)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"longitude") multipartFormData.appendBodyPart(data:"India".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"location") }, encodingCompletion: { encodingResult in switch encodingResult { case .Success(let upload, _, _): upload.responseJSON { request, response, JSON, error in } case .Failure(let encodingError): } } )

EDITAR 1: para aquellos que intentan enviar una matriz en lugar de flotante, int o cadena, pueden convertir su matriz o cualquier tipo de estructura de datos en Json String, pasar esta cadena JSON como una cadena normal. Y analiza esta cadena json en el backend para obtener la matriz original


para alamofire 4 use esto ..

Alamofire.upload(multipartFormData: { (multipartFormData) in multipartFormData.append(fileUrl, withName: "video") //fileUrl is your file path in iOS device and withName is parameter name }, to:"http://to_your_url_path") { (result) in switch result { case .success(let upload, _ , _): upload.uploadProgress(closure: { (progress) in print("uploding") }) upload.responseJSON { response in print("done") } case .failure(let encodingError): print("failed") print(encodingError) } }


Para Swift 4.2 / Alamofire 4.7.3

Alamofire.upload(multipartFormData: { multipart in multipart.append(fileData, withName: "payload", fileName: "someFile.jpg", mimeType: "image/jpeg") multipart.append("comment".data(using: .utf8)!, withName :"comment") }, to: "endPointURL", method: .post, headers: nil) { encodingResult in switch encodingResult { case .success(let upload, _, _): upload.response { answer in print("statusCode: /(answer.response?.statusCode)") } upload.uploadProgress { progress in //call progress callback here if you need it } case .failure(let encodingError): print("multipart upload encodingError: /(encodingError)") } }

También puede echar un vistazo a CodyFire lib, que hace que las llamadas a la API sean más fáciles usando Codable para todo. Ejemplo para llamadas multiparte con CodyFire

//Declare your multipart payload model struct MyPayload: MultipartPayload { var attachment: Attachment //or you could use just Data instead var comment: String } // Prepare payload for request let imageAttachment = Attachment(data: UIImage(named: "cat")!.jpeg(.high)!, fileName: "cat.jpg", mimeType: .jpg) let payload = MyPayload(attachment: imageAttachment, comment: "Some text") //Send request easily APIRequest("endpoint", payload: payload) .method(.post) .desiredStatus(.created) //201 CREATED .onError { error in switch error.code { case .notFound: print("Not found") default: print("Another error: " + error.description) } }.onSuccess { result in print("here is your decoded result") } //Btw normally it should be wrapped into an extension //so it should look even easier API.some.upload(payload).onError{}.onSuccess{}

Puedes echar un vistazo a todos los ejemplos en el archivo Léame de lib


Swift 3 / Alamofire 4.0 (Anexo a la respuesta aceptada )

Para agregar a multipartFormData en Swift 3 / Alamofire 4.0, utilice el siguiente método de MultipartFormData :

public func append(_ data: Data, withName name: String) { /* ... */ }

Y, para convertir String a Data , los data(using:) método data(using:) de String . P.ej,

multipartFormData.append("comment".data(using: .utf8)!, withName: "comment")


func funcationname() { var parameters = [String:String]() let apiToken = "Bearer /(UserDefaults.standard.string(forKey: "vAuthToken")!)" let headers = ["Vauthtoken":apiToken] let mobile = "/(ApiUtillity.sharedInstance.getUserData(key: "mobile"))" parameters = ["first_name":First_name,"last_name":last_name,"email":Email,"mobile_no":mobile] print(parameters) ApiUtillity.sharedInstance.showSVProgressHUD(text: "Loading...") let URL1 = ApiUtillity.sharedInstance.API(Join: "user/update_profile") let url = URL(string: URL1.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) var urlRequest = URLRequest(url: url!) urlRequest.httpMethod = "POST" urlRequest.allHTTPHeaderFields = headers Alamofire.upload(multipartFormData: { (multipartFormData) in multipartFormData.append(self.imageData_pf_pic, withName: "profile_image", fileName: "image.jpg", mimeType: "image/jpg") for (key, value) in parameters { multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key) } }, with: urlRequest) { (encodingResult) in switch encodingResult { case .success(let upload, _, _): upload.responseJSON { response in if let JSON = response.result.value { print("JSON: /(JSON)") let status = (JSON as AnyObject).value(forKey: "status") as! Int let sts = Int(status) if sts == 200 { ApiUtillity.sharedInstance.dismissSVProgressHUD() let UserData = ((JSON as AnyObject).value(forKey: "data") as! NSDictionary) ApiUtillity.sharedInstance.setUserData(data: UserData) } else { ApiUtillity.sharedInstance.dismissSVProgressHUD() let ErrorDic:NSDictionary = (JSON as AnyObject).value(forKey: "message") as! NSDictionary let Errormobile_no = ErrorDic.value(forKey: "mobile_no") as? String let Erroremail = ErrorDic.value(forKey: "email") as? String if Errormobile_no?.count == nil {} else { ApiUtillity.sharedInstance.dismissSVProgressHUDWithError(error: Errormobile_no!) } if Erroremail?.count == nil {} else { ApiUtillity.sharedInstance.dismissSVProgressHUDWithError(error: Erroremail!) } } } } case .failure(let encodingError): ApiUtillity.sharedInstance.dismissSVProgressHUD() print(encodingError) } } }