2015-08-11 2 views
34

Я использую Alamofire в первый раз. Я использую последнюю версию Alamofire 1.3.1. Я хочу отправить одно изображение, одно видео и некоторые параметры POST в один вызов API. Я использую данные многостраничной формы. Модуль mutipart работает. Я столкнулся с проблемой отправки дополнительных параметров POST params. Ниже мой код. «params» - это словарь, содержащий дополнительные параметры? Как добавить эти параметры POST в запрос. Пожалуйста, помогитеОтправить параметры POST с помощью MultipartFormData, используя Alamofire, в iOS Swift

 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): 

      } 
     } 
    ) 
+1

можно дублировать http://stackoverflow.com/questions/26121827/uploading-file-with-parameters-using-alamofire –

ответ

55

Я нашел решение :) наконец.

Мы можем добавлять данные в запрос как multipartformdata.

Ниже приведен мой код.

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): 

      } 
     } 
    ) 
+0

Если у меня есть массив в качестве параметра, то. –

+0

Вам придется преобразовать массив в строку. Невозможно отправить массив в параметры. – Ankush

+0

Хорошо, что мой backend pHP хочет, чтобы я отправлял массив в качестве параметра, как этот API работает для android. Поэтому, если я отправлю его кодировку в строку, поэтому мне также необходимо иметь модификации в моем backend pHP. –

14

В Alamofire 4 важно, чтобы добавить данные тела перед тем вы добавляете файл данных!

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, 
[...] 
+0

как насчет аудиофайла? - Я пытаюсь отправить аудиофайл в этой форме: multipartFormData.append (audioLocalPath, withName: "file", fileName: "file", mimeType: "application/octet-stream"), но возникает эта ошибка: multipartEncodingFailed (Alamofire.AFError .MultipartEncodingFailureReason.bodyPartFileNotReachableWithError (файл: /// var/mobile/Containers/....... /Documents/item.mp3, NSUnderlyingError = 0x16049100 {Ошибка домена = NSPOSIXErrorDomain Код = 2 "Нет такого файла или каталога"}})) - где проблема? -бад-запрос или плохой аудио-путь? – Saeid

+0

'Нет такого файла или каталога' выглядит как неудачный путь к файлу –

+0

да! - Я знаю, что это плохой путь, но я пытаюсь получить путь в пути: 'let localPath = audioURL.appendingPathComponent (audioName!)', и он работает для изображения, но не для аудио – Saeid

9

Это, как я решить мою проблему

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) 
     } 


    } 
5

Swift 3/Alamofire 4,0(Дополнение к accepted answer)

Для добавления к multipartFormData в Swift 3/Alamofire 4,0 , используйте следующий метод: MultipartFormData:

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

И, чтобы преобразовать String в Data, метод data(using:)String. Например,

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

спасибо. У вас есть пример с параметром' URLRequestConvertible'? –

+0

Мне нужно добавить данные Int, чтобы что ? Не могли бы вы мне помочь ? –

0

для alamofire 4 используют это ..

 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) 

      } 
     } 
2

Как и в Swift 3.x для загрузки изображения с параметром мы можем использовать ниже 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) 
      } 

     } 

    } 

Note: Additionally if our parameter is array of key-pairs then we can use

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

Ну, поскольку данные многостраничной формы предназначены для использования f или двоичной (и для текстовой) передачи данных, я считаю, что плохая практика - отправлять данные в кодировке String поверх нее.

Другим недостатком является невозможность отправки более сложных параметров, таких как JSON.

При этом лучшим вариантом было бы отправлять все данные в двоичной форме, то есть как данные.

Скажи мне нужно отправить эти данные

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

...наряду с изображением пользователя:

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

За что я хотел бы преобразовать, что текстовые данные в формате JSON, а затем в двоичную вместе с изображением:

//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) 

А потом, наконец, отправить его по запросу Multipart Форма данных:

Alamofire.upload(multipartFormData: { (multiFoormData) in 
     multiFoormData.append(userData, withName: "user") 
     multiFoormData.append(data, withName: "picture", mimeType: "image/png") 
    }, to: url) { (encodingResult) in 
     ... 
    } 
Смежные вопросы