[Résolu] Envoyer un fichier png sur un serveur avec NSURLConnection

RomheinRomhein Membre
octobre 2014 modifié dans API UIKit #1

Bonjour à  tous !

 

Je rencontre actuellement un problème pour envoyer un fichier png sur mon serveur...

Donc pour faire simple je prends une photo avec la caméra de l'iphone et je voudrais stocker cette photo comme photo de profil sur mon serveur. Tout se passe bien au niveau de la prise de photo mais c'est l'envoi de fichier qui fonctionne pas : j'ai l'impression que la méthode POST ne fonctionne pas.

 



- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *profil =[info objectForKey:UIImagePickerControllerEditedImage];

[photoProfil setImage:[self imageWithImage:profil scaledToSize: CGSizeMake(100, 100)] forState:normal];

//stockage dans la sandbox
NSString *imageProfil = [NSHomeDirectory()stringByAppendingPathComponent: @Documents/imageProfil.png];
NSData* imageData = UIImagePNGRepresentation([self imageWithImage:profil scaledToSize: CGSizeMake(100, 100)]);
[imageData writeToFile: imageProfil atomically:NO];


/**************************
chargement sur le serveur
***************************/

NSString *chemin=[NSString stringWithFormat: @/downloadTest.php];

NSURL *url =[[NSURL alloc] initWithScheme:@http host:@test.site-gratuit.ch path:chemin];

NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
NSData *imageData2 = UIImagePNGRepresentation([self imageWithImage:profil scaledToSize: CGSizeMake(100, 100)]);


NSMutableData *body = [NSMutableData data];
NSString *boundary = @ 14737809831466499882746641449;
NSString *contentType = [NSString stringWithFormat:@multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @Content-Type];

[body appendData:[[NSString stringWithFormat:@\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@Content-Disposition: form-data; name=\userfile\"; filename=\"photoProfil.png\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@Content-Type: image/png\r\n\r\n dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData2]];
[body appendData:[[NSString stringWithFormat:@\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];

// Methode POST pour la requete
[request setHTTPMethod:@POST];
[request setHTTPBody:body];

NSLog(@le body :%@",body);

// requetePOST est une instance
requetePOST = [[NSURLConnection alloc] initWithRequest:request delegate:self];

[requetePOST start];

if (!requetePOST){
NSLog(@Erreur de connexion);
}


[self dismissViewControllerAnimated:YES completion:nil];


}
- (NSURLRequest *) connection:(NSURLConnection*) connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
{
if (response) {
NSLog(@Ca redirige);
NSMutableURLRequest *r = [requetePOST mutableCopy];
[r setURL: [request URL]];
return r;
} else {
NSLog(@Ca redirige pas);
NSLog(@requete %@",connection);
return request;
}
}

- (void) connection:(NSURLConnection*) connection didFailWithError:(NSError *)error
{
NSLog(@erreur);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
donneesRecues=data;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{

NSArray *json = [NSJSONSerialization JSONObjectWithData:donneesRecues options:0 error:nil];

NSInteger resultat = [json[0] integerValue];
NSLog(@resultat : %d,resultat);

}


 

 

J'ai regardé pas mal de sujet dessus, et il y a pourrait y avoir un problème de redirection que je n'ai pas trop saisi...

 

Enfin voila mon fichier php, pas très sécur mais c'est juste pour tester :

 



<?php

try
{

// ce fichier upload les photos de profils sur le serveur
$uploaddir = '/photoProfil/';
$file = basename($_FILES['userfile']['name']);
$uploadfile = $uploaddir . $file;

if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
$retour[]=1; //pour test
}else{

$retour[]=2; //pour test
}
echo json_encode($retour);

}
catch (Exception $e)
{

die('Erreur : ' . $e->getMessage());
}



?> 

  

Quand je fais une requête sans le fichier png avec un GET ça fonctionne, je reçois ... je sais pas trop où est le problème... le coup de json ne sert à  rien ici, mais c'est pour la suite, je souhaiterai retourner certaines infos.

 

Merci de votre aide !

 


Réponses

  • CéroceCéroce Membre, Modérateur

    J'avoue, je n'ai que survolé le code.


     


    Qu'entends-tu par "ça ne marche pas" ?


    La requête n'aboutit pas, tu reçois un timeout, ou alors ça passe, mais ton serveur ne réagit pas ?


    As-tu regardé les logs du serveur http ?


  • oui effectivement j'ai pas décris l'erreur -_-'


     


    En fait il y en a pas, j'ai simplement aucun retour.


    Par exemple quand j'affiche les datas qui sont en retour et au format json, elles sont à  null. Donc pas de prob de requête (elle passe), pas de prob de timeout.


    Le serveur réagit uniquement quand je mets en commentaire le body de la requête et la méthode POST : il renvoie alors "2" (quand je commente dans le php tout ce qui touche à  l'upload du fichier).


    Quand je ne commente pas les lignes d'upload dans le php, il retourne null.


    Si je me connecte directement au php, il me retourne cela comme erreur :


    Notice: Undefined index: userfile in /var/www/virtual/test.site-gratuit.ch/htdocs/downloadTest.php  on line 8


    Ce qui me parait normal vu que j'ai rien envoyé :)

  • CéroceCéroce Membre, Modérateur

    Non, mais ça c'est c'est le log d'erreur de php.


    Je te parle du log des requêtes du serveur web (sans doute Apache ou nginx).


    Tu dois voir passer la requête, peut-être son contenu et la méthode HTTP utilisée?


  • ah oui voila un log quand j'essaye la fonction :


    [07/Oct/2014:22:52:18 +0200] "POST /downloadTest.php HTTP/1.1" 403 567 "-" "Test%20Me/1.0 CFNetwork/672.1.14 Darwin/14.0.0"

  • CéroceCéroce Membre, Modérateur

    Bon, eh bien déjà , ça veut dire que le POST est bien reçu par le serveur.


     


    Ce qui m'étonne c'est qu'aucune méthode déléguée de NSURLConnection ne soit appelée.


    Si tu la conserves en variable d'instance, alors la NSURLConnection doit être retenue en mémoire. Et tu t'es bien mis en délégué.


    C'est bien simple, une des méthode déléguée doit être appelée, parce que soit le serveur répond à  la requête ou bien ça foire.


  • RomheinRomhein Membre
    octobre 2014 modifié #7

    Excuse moi j'ai du mal m'exprimer dans mes réponses.


    En fait je pense que les méthodes déléguées de NSURLConnection sont appelées.


    Par exemple dans ma console je reçois:


    "ça redirige pas" (appel de la méthode willSendRequest)


    et aussi "résultat : 0" (appel de la méthode connectiondidFinishLoading)


    Mais par exemple cette dernière renvoie la réponse de mon serveur (ici j'ai mis $retour =2 ) quand j'utilise la méthode GET (sans fichier du coup) au lieu de POST.


  • CéroceCéroce Membre, Modérateur
    Regarde sur ton serveur ce que contiennent exactement les variables $_POST, $_FILE mais aussi $_GET (oui, parce qu'en php, les arguments de l'URL sont dans $_GET même quand on fait du POST. Faut pas chercher, c'est php).
    Il y a aussi une variable qui s'appelle $HTTP_RAW_POST_DATA.

    De base, php ne sait gérer que le POST "Form" (le fait que ce langage soit le plus courant pour le développement web me dépasse).
  • RomheinRomhein Membre
    octobre 2014 modifié #9

    Bon voila l'erreur que me retourne mon serveur finalement (j'avais donné le log d'accès, c'est pas encore super fluide chez moi^^) :


     


    [Tue Oct 07 22:52:19 2014] [error] [client 82.65.46.145] ModSecurity: Access denied with code 403 (phase 2). Match of "eq 0" against "REQBODY_ERROR" required. [file "/etc/apache2/activated_rules/00_asl_z_antievasion.conf"] [line "36"] [id "330791"] [msg "Failed to parse request body. This may be an impedence mismatch attack, a broken application or a broken connection. This is not a false positive. Check your application or client for errors."] [data "Multipart parsing error: Multipart: Duplicate part header: Content-Type."] [severity "CRITICAL"] [tag "no_ar"] [hostname "test.site-gratuit.ch"] [uri "/downloadTest.php"] [unique_id "VDRSgrIgI60AAJ6-Zj8AAAAR"]


     


    et aussi :


     


    [Wed Oct 08 08:48:53 2014] [error] [client 82.65.46.145] FastCGI: server "/var/lib/apache2/fastcgi/php5-fcgi-vwm.site-gratuit.ch" stderr: PHP message: PHP Notice: Undefined index: userfile in /var/www/virtual/vwm.site-gratuit.ch/htdocs/downloadVWM.php on line 9


     


     


    Donc si je comprends bien c'est dans la construction du body que j'ai un prob : "Duplicate part header: Content-Type". mais aussi "userfile" n'est pas défini, pourtant je l'ai bien défini dans mon body. J'ai pris exemple sur des tutus, j'ai comparé entre plusieurs et ils mettent la même structure donc je vois pas trop :/


     


     


    EDIT :


    -Bon après renseignement il y a moyen que ça vienne de la taille du fichier. Donc je réduis ça et je test.


    -Apparemment ça vient pas de ça, j'ai fais une image de 10ko (avant c'était à  100ko) et ça passe pas. Donc c'est vraiment le body qui est à  revoir je pense. IL doit manquer un truc...


  • RomheinRomhein Membre
    octobre 2014 modifié #10

    Eureka ça fonctionne !


     


    Donc pour résumé :


    Problème dans le corps du fichier (au niveau des boundaries) et également dans le chemin d'accès du fichier ( "./photoProfil/" au lieu de "/photoProfil/" -_-' ). En bref rien qui ne soit pas décrit dans le log d'erreur ... 


    Merci Céroce pour le coup de main, et pour l'idée d'aller piocher dans le log d'erreur, j'aurai pas eu le réflexe sans toi.


    D'ailleurs petite question en passant, ce log d'erreur est chargé une fois par jour, il y a pas moyen de demander plus à  l'hébergeur ?


     


    PS: euh on fait comment pour marquer comme résolu?


  • CéroceCéroce Membre, Modérateur

    D'ailleurs petite question en passant, ce log d'erreur est chargé une fois par jour, il y a pas moyen de demander plus à  l'hébergeur ?

    ça dépend de l'hébergeur, mais sur un hébergement mutualisé, forcément on a moins la main.
     

    PS: euh on fait comment pour marquer comme résolu?

    Edite le titre du premier message avec l'éditeur complet.
Connectez-vous ou Inscrivez-vous pour répondre.