2016-03-28 2 views
0

Récemment, je réalise une tâche NSUrlSession pour télécharger plusieurs images dans le backend. J'ai ajouté toutes les images en représentation .png dans un tableau. J'ai converti l'ensemble du tableau en un format de base64 String et j'ai essayé d'envoyer le corps entier sous forme de chaîne.Le corps de NSMutableRequest consistant en base64encodeString est tronqué lors de l'envoi en tant que chaîne

Conversion de imageArray à cordes -

let imageArrayData: NSData = NSKeyedArchiver.archivedDataWithRootObject(imageArray) 
     let imageArrayBase64String = imageArrayData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) 

impression Ici, le tableau, je reçois -

(String) imageArrayBase64String = "YnBsaXN0MDDUAQIDBAUIIiNUJHRvcFgkb2JqZWN0c1gkdmVyc2lvblkkYXJjaGl2ZXLRBgdUcm9vdIABpQkKEBQcVSRudWxs0gsMDQ5WJGNsYXNzWk5TLm9iamVjdHOABKEPgALSEQsSE1dOUy5kYXRhTxIBe8QxiVBORw0KGgoAAAANSUhEUgAAEMAAAAsgCAIAAABnC3DjAAABGWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGBSSCwoyGESYGDIzSspCnJ3UoiIjFJgf8DAzCDDwMUgwGCUmFxc4BgQ4MMABDAaFXy7xsAIoi/rgszClMcLuFJSi5OB9B8gzk4uKCphYGDMALKVy0sKQOweIFskKRvMXgBiFwEdCGRvAbHTIewTYDUQ9h2wmpAgZyD7A5DNlwRmM4Hs4kuHsAVAbKi9ICDomJKflKoA8r2GoaWlhSaJfiAISlIrSkC0c35BZVFmekaJgiMwpFIVPPOS9XQUjAwMzRgYQOEOUf05EByejGJnEGIIgBCbI8HA4L+UgYHlD0LMpJeBYYEOAwP/VISYmiEDg4A+A8O+OcmlRWVQYxiZjBkYCPEBNDZKYi1QenUAAAAcaURPVAAAAAIAAAAAAAAFkAAAACgAAAWQAAAFkADAfM/Go8QlAABAAElEQVR4AXS8BXQcV7b3K0Pm3jt3IIlBlmzLFjMzMzMztVhqUasZ1ChmZibLsixmmSmGkB1yzIyhgZubTGJ//+rK6GW97721/muvffbZdaqqq7vqVNX+tUJijjZEKTBIztNNyNZKoeol5WlB8dnqibmaKfk68BOy1JNztVKpOkk5mgiSItPkPjLVU/K14rIOpxboJlO1YzNVE3I0IDJzayiMhmBclhoisEhOK9JHPhZPytNILdCiFGqn07STqKrJVI2UfM24rEPx2YcRzKDppRZoYxWkknM1IGxPSp52cp56epFOar5mClUjmYoN1kor0kVyWpFOejHG18E4KQXqqYUaacUaGSVa2XSdPJY+pUAtk6aVxdB" 

Création du corps -

let body = "task=doNotification&select_category=\(selectCategory!)&select_type=\(selectType!)&class=\(classid!)&repliable=\(repliable)&select_students=\(selectedStudents)&select_group=\(selectGroup!)&title=\(SbjctOrTtlTxtFld.text!)&text=\(textVieww.text!)&image=\(imageArrayBase64String)&date=\(dateText!)&time=\(timeText!)" 

impression Ici le corps, je reçois -

(String) body = "task=doNotification&select_category=exams&select_type=check&class=2&repliable=1&select_students=(\n 26,\n 25\n)&select_group=11&title=self&text=Adam <IMG_0002>&image=YnBsaXN0MDDUAQIDBAUIIiNUJHRvcFgkb2JqZWN0c1gkdmVyc2lvblkkYXJjaGl2ZXLRBgdUcm9vdIABpQkKEBQcVSRudWxs0gsMDQ5WJGNsYXNzWk5TLm9iamVjdHOABKEPgALSEQsSE1dOUy5kYXRhTxIBe8QxiVBORw0KGgoAAAANSUhEUgAAEMAAAAsgCAIAAABnC3DjAAABGWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGBSSCwoyGESYGDIzSspCnJ3UoiIjFJgf8DAzCDDwMUgwGCUmFxc4BgQ4MMABDAaFXy7xsAIoi/rgszClMcLuFJSi5OB9B8gzk4uKCphYGDMALKVy0sKQOweIFskKRvMXgBiFwEdCGRvAbHTIewTYDUQ9h2wmpAgZyD7A5DNlwRmM4Hs4kuHsAVAbKi9ICDomJKflKoA8r2GoaWlhSaJfiAISlIrSkC0c35BZVFmekaJgiMwpFIVPPOS9XQUjAwMzRgYQOEOUf05EByejGJnEGIIgBCbI8HA4L+UgYHlD0LMpJeBYYEOAwP/VISYmiEDg4A+A8O+OcmlRWVQYxiZjBkYCPEBNDZKYi1QenUAAAAcaURPVAAAAAIAAAAAAAAFkAAAACgAAAWQAAAFkADAfM/Go8QlAABAAElEQVR4AXS8BXQcV7b3K0Pm3jt3IIlBlmzLFjMzMzMztVhqUasZ1ChmZibLsixmmSmGkB1yzIyhgZubTGJ//+rK6GW97721/muvffbZdaqqq7vqVNX+tUJijjZEKTBIztNNyNZKoeol5WlB8dnqibmaKfk68BOy1JNztVKpOkk5mgiSItPkPjLVU/K14rIOpxboJlO1YzN" 

Comme vous pouvez remarquer que le corps ne passe même pas la pleine chaîne encodée du tableau et il est pas repassais les 2 derniers paramètres c'est-à-dire la date & temps.

Alors pourquoi est-ce le cas?

Appeler le service Web -

func sendAPIRequest(urlpath:NSString,body: NSString , completion: (result: NSMutableDictionary, error: AnyObject?)-> Void) -> Void 
    { 

     let url:NSURL = NSURL(string: urlpath as String)! 

     let request = NSMutableURLRequest(URL: url) 
     request.HTTPMethod = "POST" 

     let bodydata = body.dataUsingEncoding(NSUTF8StringEncoding) 
     request.HTTPBody = bodydata 



     let config = NSURLSessionConfiguration.defaultSessionConfiguration() 
     let session = NSURLSession(configuration: config) 

     let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in 

      do 
      { 

       let resultdic = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSMutableDictionary 
       //print(resultdic!) 
       completion(result: resultdic!,error: nil) 


      } 
      catch 
      { 
       print("error") 
      } 

     } 
     task.resume() 

Répondre

0

Quelques observations:

  1. On dirait que vous cherchez à body dans le débogueur. Cela tronquera la chaîne (bien que généralement elle montre des ellipses à la fin pour indiquer qu'elle a été tronquée). Je vous suggère d'essayer print(body) et voir si vous voyez toute la chaîne là.

  2. Votre selectStudents est un NSArray et lorsque vous faites une interpolation de chaîne, il inclut un caractère de nouvelle ligne. L'effet net est que cette demande x-www-form-urlencoded n'est pas bien formée et sera probablement rejetée par le serveur. Il y a deux façons de résoudre ce

    • Si votre serveur est vraiment attend une chaîne de la forme select_students=(\n 26,\n 25\n) (que je serais très surpris si c'est vraiment ce que vous voulez), vous devriez pour cent évasion cette chaîne:

      let selectedStudentsString = "selectedStudents=\(selectedStudents)".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryParameterAllowedCharacterSet())! 
      

      et qui va donner:

      selectedStudents=(%0A%20%20%20%20foo,%0A%20%20%20%20bar%0A) 
      

      URLQueryParameterAllowedCharacterSet est défini comme:

      extension NSCharacterSet { 
      
          /// Returns the character set for characters allowed in the individual parameters within a query URL component. 
          /// 
          /// The query component of a URL is the component immediately following a question mark (?). 
          /// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query 
          /// component is `key1=value1`. The individual parameters of that query would be the key `key1` 
          /// and its associated value `value1`. 
          /// 
          /// According to RFC 3986, the set of unreserved characters includes 
          /// 
          /// `ALPHA/DIGIT/"-"/"."/"_"/"~"` 
          /// 
          /// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters 
          /// for the sake of compatibility with some erroneous implementations, so this routine also allows those 
          /// to pass unescaped. 
      
      
          class func URLQueryParameterAllowedCharacterSet() -> Self { 
           return self.init(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~/?") 
          } 
      
      } 
      

      Voir https://stackoverflow.com/a/35912606/1271826 pour d'autres options d'échappement en pourcentage.Mais évitez d'utiliser stringByAddingPercentEncodingWithAllowedCharacters avec l'un des jeux de caractères existants (par exemple, URLQueryAllowedCharacterSet), car tous permettent aux caractères réservés de passer sans être échappés.

    • Si vous voulez vraiment ce reçu comme un tableau dans une requête x-www-form-urlencoded par votre code serveur, vous voudrez probablement:

      var selectedStudentsArray = [String]() 
      for index in 0 ..< selectedStudents.count { 
          selectedStudentsArray.append("selectedStudents[]=\(selectedStudents[index])") 
      } 
      let selectedStudentsString = selectedStudentsArray.joinWithSeparator("&") 
      

      et qui donnera:

      selectedStudents[]=26&selectedStudents[]=25 
      

      C'est la bonne façon d'envoyer un tableau de valeurs dans une demande x-www-form-urlencoded.

  3. Votre valeur text comprend des caractères réservés aussi. Vous devriez être pour cent échapper à cette (et tout ce qui pourrait inclure des caractères en dehors de a - z, A - Z, 0-9 et -, ., _, ~, / et ?). Encore une fois, lorsque vous faites x-www-form-urlencoded demande comme ceci, tous les caractères réservés doivent être échappés en pourcentage. Vous prenez votre tableau d'images et construisez un NSKeyedArchiver. Cela va être un gros objet opaque, blob, en ce qui concerne votre service web. Si vous avez l'intention de traiter cela comme une seule tâche sur le serveur, c'est bien, mais si vous espérez extraire les images, vous compliquerez inutilement votre vie.

    Vous pouvez:

    • Base-64 encode les images séparément et ensuite utiliser le même format que je suggère pour selectStudents, par exemple

      image[]=Bsa...JJH&image[]=5YJ...mVj 
      

      Remarque, vous devez utiliser le contenu original des données (par exemple obtenir le NSData directement à partir du fichier d'origine/actifs, évitant UIImage tout à fait) ou, si vous vraiment besoin d'aller-retour à travers un UIImage (que je déconseillerais si vous pouvez l'empêcher), puis utilisez UIImagePNGRepresentation ou UIImageJPEGRepresentation pour créer un nouveau NSData à partir du UIImage.

    • Vous pouvez envisager d'utiliser une demande multipart/form-data et les images individuelles (encore une fois, avec le commentaire ci-dessus à obtenir le NSData nonobstant) peuvent être stockés individuellement. Si vous faites une bonne multipart/form-data demande, il évite tout besoin de faire pour cent-escaping partout, aussi, base 64 évite le codage (ce qui rend la transmission 33% plus grande qu'elle doit être), etc.

Bottom line, la création correcte de ce genre de demandes est très, très compliqué, et sauf si vous voulez vraiment démêler toutes ces idiosyncrasies, je vous encourage vraiment à considérer Alamofire, qui vous permet de sortir de ces mauvaises herbes. Et si vous vous sentez vraiment obligé de réinventer la roue, je vous suggère de faire des recherches sur ces sujets individuellement, car c'est beaucoup trop large pour une seule question. Chacun de mes points ci-dessus justifie probablement une question distincte.