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

Langage Delphi Discussion :

Equivalent Delphi 7 du MultipartFormDataContent


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 978
    Par défaut Equivalent Delphi 7 du MultipartFormDataContent
    Bonjour,

    Je dois appeler une API pour déposer des documents mais le code d'exemple est en C# et je voulais éviter de faire une DLL à appeler en COM depuis Delphi.

    Je comptais remplacer
    FileStream par TFileStream
    HttpClient par IXMLHttpRequest
    PostAsync sur webclient par une gestion de thread classique

    Mais je n'ai aucune idée de l'objet Delphi 7 à utiliser pour le MultipartFormDataContent
    Edit : à priori, je ne trouve pas non plus d'équivalent pour StreamContent.

    Voici le code C#
    Code C# : 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
    using (FileStream fileStream = new FileStream(fichier, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, useAsync: false))
    {
        /* Create a stream content for the file */
        StreamContent content = new StreamContent(fileStream, BufferSize);
     
        // Create Multipart form data content, add our submitter data and our stream content
        MultipartFormDataContent formData = new MultipartFormDataContent();
        string d = DateTime.Now.ToString("yyyyMMddHHmmss");
        formData.Add(new StringContent(d), "t"); /* date de l'envoi */
        formData.Add(new StringContent(Version), "VERSION");
        formData.Add(new StringContent(Libelle), "LIBELLE");
        formData.Add(new StringContent(Description), "DESCRIPTION");
     
        /* Reference pour identifier le document. */
        string Reference = Guid.NewGuid().ToString();
        formData.Add(new StringContent(Reference), "REFERENCE");
        formData.Add(content, "filename", fichier); /* le fichier */
     
     
         // Post the MIME multipart form data upload with the file
        string url=string.Format(URLAPPLI + "api/" + "UploadFile");
        Uri address = new Uri(url);
        var webclient = new HttpClient();     
     
        /*calcul du timeout en fonction de la taille du document*/
        FileInfo file = new FileInfo(fichier);
        long Taille = file.Length;
        int timoutcalcule = (int)(Taille / 100000)+1;
        webclient.Timeout = new TimeSpan(0, 0, timoutcalcule);
     
        /* format du retour */
        //webclient.DefaultRequestHeaders.Add("Accept", "text/xml");
        webclient.DefaultRequestHeaders.Add("Accept", "text/json");
     
        // appel de L'API
        var task = webclient.PostAsync(address,formData);
        task.Wait();
        HttpResponseMessage response = task.Result;
     
        // retour en JSON
        var resp = response.Content.ReadAsAsync<RetResponse>().Result;
        if (resp.Success)
        {
            ret = resp.Message + "- Id : " + resp.Id + " - ID Interne : " + resp.InternalID.ToString();
        }
        else
        {
            ret = resp.Message + "- Id : " + resp.Id;
        }
    }

    Merci

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    IXMLHttpRequest me choque, du coup tu n'es plus en type MIME donc ce n'est plus du Multipart !

    Je note JSON, c'est une API REST ?
    Tu n'as pas du JSON en entrée et en sortie ?
    En D7, faut une lib externe mais cela se bricole avec une Template et un format ...

    genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const
      GET_TOKEN_JSON_PARAM_FMT = '{"token":"%s","refresh_token":"%s","refresh_token_key":"%s"}'; // Version rapide sans passer par un TJSONObject
    ...
          Source.WriteString(Format(GET_TOKEN_JSON_PARAM_FMT, [FToken, FRefreshToken, FRefreshTokenKey]));
    Peut-être ton entrée c'est de POST classique genre ?p1=v1&p2=v2...Il n'y a rien de plus simple que de générer la chaine de paramètre à la main

    Pas besoin de composant externe, tu as les API Windows
    Tient un code pour envoyer n'importe quel paramètre pour n'importe quelle URL

    exemple avec pour chaque Input


    tu récupéras le fichier HTML généré par le forum

    C'est du code XE2 pour le convertir en D7
    LPWSTR -> LPSTR
    RawByteString -> string

    Tu as une version plus ancienne dans la FAQ : Comment télécharger un fichier en http sans utiliser Indy ?
    Tu en trouve d'autres sur le forum

    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
    const
      BufferSize = 1024;
      accept: packed array[0..1] of LPWSTR = (PChar('text/*'), nil); // PCTSTR rgpszAcceptTypes[] = {_T(“text/*”), NULL};
    var
      ServerName, URL, Params, LocalFileName: string;
      hSession, hHTTP, hReq : HINTERNET;
      Buffer: array[1..BufferSize] of Byte;
      BufferLen: DWORD;
      sAppName: string;
      FS: TFileStream;
      Headers: string;
      Data: RawByteString;
    begin
      sAppName := ExtractFileName(Application.ExeName);
     
      hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
      try
        if not InputQuery('Download URL', 'Server Name', ServerName) then
          Exit;
     
        hHTTP := InternetConnect(hSession, PChar(ServerName), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
        try
          if not InputQuery('Download URL', 'URL', URL) then
            Exit;
     
          hReq := HttpOpenRequest(hHTTP, PChar('POST'), PChar(URL), nil, nil, @accept, 0, 1);
          try
            Headers := 'Content-Type: application/x-www-form-urlencoded; charset=utf-8';
     
            if not InputQuery('Download URL', 'Params', Params) then
              Exit;
     
            Data := UTF8Encode(Params);
            if HttpSendRequest(hReq, PChar(Headers), length(Headers), PAnsiChar(Data), length(Data)) then
            begin
              LocalFileName := StringReplace(URL, '/', '_', [rfReplaceAll]);
              if not PromptForFileName(LocalFileName, '', '.txt', 'Download URL into Local File', '', True) then
                Exit;
     
              FS := TFileStream.Create(LocalFileName, fmCreate);
              try
                BufferLen := 0;
                repeat
                  if InternetReadFile(hReq, @Buffer, BufferSize, BufferLen) then
                    FS.WriteBuffer(Buffer, BufferLen);
     
                until BufferLen = 0;
              finally
                FS.Free;
              end;
            end
            else
              raise Exception.Create('HttpOpenRequest failed. ' + SysErrorMessage(GetLastError));
          finally
            InternetCloseHandle(hReq);
          end;
        finally
          InternetCloseHandle(hHTTP);
        end;
      finally
        InternetCloseHandle(hSession);
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 978
    Par défaut
    Effectivement, c'est du JSON.
    En entrée comme en sortie ça m'a été confirmé par le développeur de l'api.
    Former du JSON ne devrait pas poser de problème je pense (j'ai déjà SuperObject dans le projet).

    Utiliser les API Windows, tu veux certainement parler de ce qui se trouve dans WinInet.

    Je ne suis pas très à l'aise avec le sujet et je n'avais pas conscience de la notion de multi part.
    ça me donne à présent une idée de ce que je dois chercher.

    Au fait cette URL ne donne rien.
    http://www.developpez.net/forums/sea...archid=9661936

  4. #4
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 978
    Par défaut
    J'ai trouvé cette page qui à l'air pas mal.
    http://www.delphigroups.info/2/5/492268.html
    J'essaie de bricoler un truc et je vous tiens au courant

  5. #5
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 978
    Par défaut
    Un coup dans l'eau.
    Je ne peux pas utiliser Indy.
    A priori, ça ne passerait pas les proxy.

    Tout les exemples utilisant directement wininet que j'ai pu trouver envoient simplement du texte.
    J'ai besoin d'envoyer n'importe quel fichier (surtout du PDF et de documents office).

    Je n'arrive pas non plus à comprendre sous quelle forme je dois passer les informations.
    Puisqu'il s'agit de JSON je pensais à passer un truc de ce genre via la méthode Send:
    Code JSON : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    {
    	"t": "20161216095800",
    	"VERSION": "Ma version",
    	"LIBELLE": "Un libellé",
    	"DESCRIPTION": "Une description",
    	"REFERENCE": "4DA9B350-1C9B-479E-8C62-D5AAF1296A16"
    }

    Mais comment intégrer mon flux là dedans ?

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    As-tu vu mon code dans ma réponse précédente utilisant HttpSendRequest qui utilise justement une RawByteString parce que la donnée doit être géré comme un Binaire
    En D7, utilise un Array of Byte et un TFileStream (ou même un TMemoryStream)

    voici les extraits qui change

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      Headers: string;
      Data: RawByteString;
    begin
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      Headers: string;
      Data: array of Byte;
      FS: TFileStream;
    begin
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      Headers: string;
      FM: TMemoryStream;
      FS: TFileStream;
    begin
    .

    ainsi que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Data := UTF8Encode(Params);
    if HttpSendRequest(hReq, PChar(Headers), length(Headers), PAnsiChar(Data), length(Data)) then
    begin
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    FS.LoadFromFile(LePFD);
    SetLength(Data, FS.Size);
    FS.Read(Data[0], FS.Size);
    if HttpSendRequest(hReq, PChar(Headers), length(Headers), PAnsiChar(Data[0]), length(Data)) then
    begin
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    FS.LoadFromFile(LePFD);
    FS.Seek(0, soFromBeginning); // en D7, je sais plus si c'est soFromBeginning ou soBeginning
    FM.LoadFromStream(FS);
    if HttpSendRequest(hReq, PChar(Headers), length(Headers), PAnsiChar(FM.Memory), length(Data)) then
    begin

    Pour le JSON, je pense qu'un encodage UTF8 est nécessaire
    Pour un PDF, tout dépend comment tu dois l'envoyer,
    - Si c'est directement, le binaire, tu dois voir avec l'auteur ce que tu dois mettre comme ContentType, CharSet et ContentEncoding, ce qui donne un truc genre 'Content-Type: application/octet-stream'.
    - Si c'est via un JSON, cela nécessite probablement un encodage en Base64 qui a l'avantage de n'utiliser QUE des caractères basiques qui ne souffrent d'aucune manipulation de CharSet donc 'Content-Type: application/json; charset=utf-8'.

    Un JSON avec le PDF en Binaire

    Code json : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    {
    	"t": "20161216095800",
    	"VERSION": "Ma version",
    	"LIBELLE": "Un libellé",
    	"DESCRIPTION": "Une description",
    	"REFERENCE": "4DA9B350-1C9B-479E-8C62-D5AAF1296A16"
            "Content": "AAB3... un tas de lettre ...G5Z6=="
    }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. equivalent delphi en c#
    Par b.grellee dans le forum Windows Forms
    Réponses: 7
    Dernier message: 10/04/2009, 12h12
  2. Equivalence Delphi / C++
    Par ambessa dans le forum Langage
    Réponses: 1
    Dernier message: 09/07/2008, 15h50
  3. Environnement equivalent à Delphi et C++ Builder
    Par b_reda31 dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 04/02/2008, 23h37
  4. Equivalents Delphi de quelques variables VB
    Par AL1986 dans le forum Langage
    Réponses: 6
    Dernier message: 19/08/2007, 12h26
  5. Equivalent Delphi de la classe App de VB
    Par AL1986 dans le forum Langage
    Réponses: 7
    Dernier message: 07/08/2007, 17h07

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