IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Requete HTTP POST MIME - Upload de fichier


Sujet :

Réseau C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 17
    Points : 12
    Points
    12
    Par défaut Requete HTTP POST MIME - Upload de fichier
    Bonjour, je suis débutant et j'ai créer une fonction pour uploader un fichier sur un serveur php apache via le protocole http et le standard mime.

    Le problème est pour uploader une image jpg, j'avais penser l'encoder en base_64 et rajouter Content-Transfer-Encoding:base64 dans le header de la requête, mais apparemment ça ne semble pas possible avec le protocole http (voir rfc2616 - 19.4.5) si je l'encode en base 64 le fichier recut sur le serveur php reste en base 64 et n'est pas décodé ... et si je ne converti pas le fichier et l'envoi tel qu'elle(comme dans le code ci-dessous) cela ne marche pas non plus ... comment puis-je faire ?


    Merci d'avance pour vos réponse ..
    désolé si je n'ai pas été assez clair, mais n'hésitez pas à poser des questions ..
    Chouquette .


    Mon Code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    void UPLOAD()
    {
     
      WSADATA WSAData;
       int erreur = WSAStartup(MAKEWORD(2,0), &WSAData);
       SOCKET sock;
       SOCKADDR_IN sin;
       char buffer[1024] = "";
     
        /* Si les sockets Windows fonctionnent */
        if(!erreur)
        {
            /* Création de la socket */
            sock = socket(AF_INET, SOCK_STREAM, 0);
     
            /* Configuration de la connexion */
                    struct hostent *ipserver;
                    ipserver = gethostbyname(url_server);
                    memcpy(&sin.sin_addr,ipserver->h_addr,ipserver->h_length);
            sin.sin_family = AF_INET;
            sin.sin_port = htons(80);
     
            /* Si l'on a réussi à se connecter */
            if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
            {
     
                            FILE* fichier = NULL;
                            char chaine[45000];
                char commande[50000];
                            char variables[60000];
                            fichier = fopen("test.jpg", "r");
     
                            sprintf(variables,"--frontier\r\nContent-Disposition: form-data; name=\"envoyer\"\r\n\r\noui\r\n--frontier\r\nContent-Disposition: form-data; name=\"fichier\"; filename=\"test.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n");
     
                            if (fichier != NULL)
                            {
                                    while (fgets(chaine, 45000, fichier) != NULL) // On lit le fichier tant qu'on ne reçoit pas d'erreur (NULL)
                                    {
                                     strcat(variables,chaine);
                                    }
                            }        
     
                            strcat(variables,"\r\n--frontier--\r\n");
                            sprintf(commande,"POST %s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\nContent-Type: multipart/form-data; boundary=\"frontier\"\r\nMIME-version: 1.0\r\nContent-Length:%d\r\n\r\n%s",http_req_path,url_server,strlen(variables),variables);
                            send(sock,commande,strlen(commande)+1,0);
     
                            char response [1024] ="";
                            while (recv(sock,buffer, 1024, 0) > 0)
                {
                    strcat(response, buffer);
                }
                            char *resultatfinal = strstr(response, "\r\n\r\n")+4;
                            printf("%s", resultatfinal);
     
     
     
            }
            /* sinon, on affiche "Impossible de se connecter" */
            else
            {
                printf("Impossible de se connecter\n");
            }
     
            /* On ferme la socket */
            closesocket(sock);
     
            WSACleanup();
            }
     
    }

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    regarde du côté de la librairie winhttp, c'est prévu pour les transaction http (comme son nom l'indique)

  3. #3
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Olphébus Voir le message
    si je ne converti pas le fichier et l'envoi tel qu'elle(comme dans le code ci-dessous) cela ne marche pas non plus ... comment puis-je faire ?
    Le fichier a transmettre étant binaire, tu n'as absolument pas le droit d'utiliser les méthodes des fichiers textes. Il faut :

    - ouvrir en binaire avec "rb"
    - utiliser la lecture par blocs avec fread().

    Mais est-ce possible au sein du protocole http, ça m'étonnerait... car comme apparemment, on ne transmet pas la longueur, je ne vois pas comment le serveur saurait que c'est terminé...

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Dans le protocole HTTP, il y a un champs "Content-Length". Donc le récepteur peut connaitre la longueur des données à lire.

    Je pense aussi que si c'est un fichier binaire, il doit être transmis en base64.

  5. #5
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Dans le protocole HTTP, il y a un champs "Content-Length". Donc le récepteur peut connaitre la longueur des données à lire.

    Je pense aussi que si c'est un fichier binaire, il doit être transmis en base64.
    Par curiosité (et par flemme de trouver la doc) en base 64, il faut 64 'chiffres', alors :

    A-Z : 26
    a-z : 26
    0-9 : 10

    Total 62. C'est quoi les 2 derniers ?

    http://fr.wikipedia.org/wiki/Base64

    EDIT : + et /

    Il y a aussi = dit 'complément' ? Ah OK, c'est une sorte de 'NOP' pour compléter le groupe de 24 bit (4 caractères de 6 bit)

    AB==
    ABC=
    ABCD

    Ca ne me parait pas si compliqué que ça de faire un encodeur Base64. Il faut connaitre les opérateurs bits, mais à part ça...

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 581
    Points
    41 581
    Par défaut
    En fait, si j'ai bien compris, il arrive que les deux caractères supplémentaires changent.

    Il y a un temps, j'avais posté un code C permettant de décoder avec le choix de caractères voulu: http://www.developpez.net/forums/d57...s/#post3401966

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 17
    Points : 12
    Points
    12
    Par défaut
    Merci beaucoup pour votre aide ! ca semble pouvoir fonctionner si je l'envoi en mode binaire, mais j'ai encore un petit probleme car j'ai modifier le code, j'ouvre le fichier en mode binaire, j'utilise fread mais la requete envoi malgré tout du texte et non du binaire comme je le souhaite..

    est-ce dut à la fonction strcat(variables,bufferFichier); qui remetterais le binaire en texte ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    void UPLOAD()
    {
     
      WSADATA WSAData;
       int erreur = WSAStartup(MAKEWORD(2,0), &WSAData);
       SOCKET sock;
       SOCKADDR_IN sin;
       char buffer[1024] = "";
     
        /* Si les sockets Windows fonctionnent */
        if(!erreur)
        {
            /* Création de la socket */
            sock = socket(AF_INET, SOCK_STREAM, 0);
     
            /* Configuration de la connexion */
    		struct hostent *ipserver;
    		ipserver = gethostbyname(url_server);
    		memcpy(&sin.sin_addr,ipserver->h_addr,ipserver->h_length);
            sin.sin_family = AF_INET;
            sin.sin_port = htons(80);
     
            /* Si l'on a réussi à se connecter */
            if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
            {
     
    			FILE* fichier = NULL;
    			fichier = fopen("test.jpg", "rb");
    			char * commande;
    			char * bufferFichier;
    			char * variables;
    			long lSize;
     
    			// obtain file size:
    			fseek (fichier , 0 , SEEK_END);
    			lSize = ftell(fichier);
    			rewind (fichier);
     
    			// allocate memory to contain the whole file:
    			bufferFichier = (char*) malloc (sizeof(char)*lSize);
    			commande = (char*) malloc (sizeof(char)*lSize+8000);
    			variables = (char*) malloc (sizeof(char)*lSize+15000);
     
    			sprintf(variables,"--frontier\r\nContent-Disposition: form-data; name=\"envoyer\"\r\n\r\noui\r\n--frontier\r\nContent-Disposition: form-data; name=\"fichier\"; filename=\"test.jpg\"\r\nContent-Type: image/jpeg\r\nContent-Transfer-Encoding: binary\r\n\r\n");
     
    			if (fichier != NULL)
    			{
    				fread(bufferFichier,1,lSize,fichier);
    			}	
     
    			strcat(variables,bufferFichier);
    			strcat(variables,"\r\n--frontier--\r\n");
    			sprintf(commande,"POST %s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\nContent-Type: multipart/form-data; boundary=\"frontier\"\r\nMIME-version: 1.0\r\nContent-Length:%d\r\n\r\n%s",http_req_path,url_server,(strlen(variables)+lSize),variables);
    			send(sock,commande,strlen(commande)+1,0);
    			printf("%s", commande);
    			free(commande);
    			free(variables);
    			free(bufferFichier);
     
    			char response [1024] ="";
    			while (recv(sock,buffer, 1024, 0) > 0)
                {
                    strcat(response, buffer);
                }
    			char *resultatfinal = strstr(response, "\r\n\r\n")+4;
    			printf("%s", resultatfinal);
     
            }
            /* sinon, on affiche "Impossible de se connecter" */
            else
            {
                printf("Impossible de se connecter\n");
            }
     
     
            /* On ferme la socket */
            closesocket(sock);
     
            WSACleanup();
    	}
     
    }

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Olphébus Voir le message
    Merci beaucoup pour votre aide ! ca semble pouvoir fonctionner si je l'envoi en mode binaire, mais j'ai encore un petit probleme car j'ai modifier le code, j'ouvre le fichier en mode binaire, j'utilise fread mais la requete envoi malgré tout du texte et non du binaire comme je le souhaite..

    est-ce dut à la fonction strcat(variables,bufferFichier); qui remetterais le binaire en texte ?
    Il faut arréter le délire. Programmer une application réseau nécessite une maitrise du langage C. Si tu ne sais pas que strcat() ne fonctionne que pour les chaines de caractères, il faut revoir les bases du C avant de se lancer dans une telle application.

    Le C, ça ne s'improvise pas, ça s'apprend sérieusement.

    D'autre part, pour en revenir à ton application, il est fort probable qu'il faille coder le fichier en base64, sinon, on a pas de délimiteurs.

    La réponse est dans le document de spécification du protocole que tu utilises (une RFC, probablement).

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 17
    Points : 12
    Points
    12
    Par défaut
    Les différents fichier dans une requête mime sont délimités par les boundary. ( voir http://en.wikipedia.org/wiki/MIME ) . et la taille totale de la requête mime est précisé dans le header avec Content-Length:

    J'ai aussi penser comme toi qu'il fallait envoyer le fichier en base 64 mais cela ne semble pas fonctionner car quand le serveur apache reçoit le fichier, si je l'ouvre avec un editeur texte je retrouve le fichier encore converti en base 64, apache ne le décode pas malgré que j'ai placé dans l'entête content-transfer-encoding:base64.
    Je pourrais bien sur décodé le fichier avec php, mais je ne pense pas que ce soit la bonne solution...

    Sinon pour strcat je suis débutant en c et je n'ai jamais manipuler de fichier en binaire avant (juste en texte jusqu'à maintenant) ...

  10. #10
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    strcat est utilisé pour concaténer une chaine de caractères à une autre chaine de caractères. Le délimiteur de fin de chaine est le caractère valant 0.

    Un fichier binaire peut contenir n'importe quoi comme octets et donc précisément le code 0. Donc si tu utilises strcat sur du binaire, il va s'arrêter sur le premier octet à 0 et donc peut être en milieu de fichier.

    Pour du binaire, il faut utiliser memcpy() mais avant, il faut calculer l'offset de recopie dans le buffer de destination ainsi que la longueur à copier tout en étant sûr au préalable d'avoir suffisamment de place dans le buffer de destination.

Discussions similaires

  1. probleme Requete HTTP (post)
    Par Pyroclem dans le forum Débuter
    Réponses: 1
    Dernier message: 18/03/2009, 23h52
  2. Réponses: 1
    Dernier message: 17/12/2008, 15h15
  3. Réponses: 2
    Dernier message: 04/11/2008, 15h04
  4. [curl] requete http post ( simuler envoi de formulaire )
    Par mikebranque dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 07/07/2008, 21h55
  5. Requete HTTP Post et Cookies
    Par Ptitkarl dans le forum Langage
    Réponses: 17
    Dernier message: 24/04/2008, 15h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo