PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, November 2, 2022

[FIXED] How to send a file AND other POST data with Synapse

 November 02, 2022     ararat-synapse, delphi, file, http, post     No comments   

Issue

Delphi used: 2007.

Hello,

I have a simple web page with two text input and one file input. Now, for the form to be sent, both the text inputs and the file input have to be filled. With Synapse, I know how to upload a file (HttpPostFile) and how to post data (HttpMethod). However, I don't know how to do both.

After looking at the source code of Synapse, I guess I have to "format" my data with boundaries or something like that. I guess I should have one boundary for my input file and another boundary for my text inputs. I found an article on the subject, but it's about sending email attachments. I tried to reproduce what they said with Synapse, with no results.

Code for HttpPostFile:

function HttpPostFile(const URL, FieldName, FileName: string;
  const Data: TStream; const ResultData: TStrings): Boolean;
var
  HTTP: THTTPSend;
  Bound, s: string;
begin
  Bound := IntToHex(Random(MaxInt), 8) + '_Synapse_boundary';
  HTTP := THTTPSend.Create;
  try
    s := '--' + Bound + CRLF;
    s := s + 'content-disposition: form-data; name="' + FieldName + '";';
    s := s + ' filename="' + FileName +'"' + CRLF;
    s := s + 'Content-Type: Application/octet-string' + CRLF + CRLF;
    WriteStrToStream(HTTP.Document, s);
    HTTP.Document.CopyFrom(Data, 0);
    s := CRLF + '--' + Bound + '--' + CRLF;
    WriteStrToStream(HTTP.Document, s);
    HTTP.MimeType := 'multipart/form-data; boundary=' + Bound;
    Result := HTTP.HTTPMethod('POST', URL);
    if Result then
      ResultData.LoadFromStream(HTTP.Document);
  finally
    HTTP.Free;
  end;
end;

Thank you.


Solution

Your code is close. You are only sending your file field but not your text fields. To do all three, try this instead:

function HttpPostFile(const URL, InputText1FieldName, InputText1, InputText2FieldName, InputText2, InputFileFieldName, InputFileName: string; InputFileData: TStream; ResultData: TStrings): Boolean; 
var 
  HTTP: THTTPSend; 
  Bound: string; 
begin 
  Bound := IntToHex(Random(MaxInt), 8) + '_Synapse_boundary'; 
  HTTP := THTTPSend.Create; 
  try 
    WriteStrToStream(HTTP.Document,
      '--' + Bound + CRLF +
      'Content-Disposition: form-data; name=' + AnsiQuotedStr(InputText1FieldName, '"') + CRLF +
      'Content-Type: text/plain' + CRLF +
      CRLF); 
    WriteStrToStream(HTTP.Document, InputText1); 
    WriteStrToStream(HTTP.Document,
      CRLF +
      '--' + Bound + CRLF +
      'Content-Disposition: form-data; name=' + AnsiQuotedStr(InputText2FieldName, '"') + CRLF +
      'Content-Type: text/plain' + CRLF +
      CRLF); 
    WriteStrToStream(HTTP.Document, InputText2); 
    WriteStrToStream(HTTP.Document,
      CRLF +
      '--' + Bound + CRLF +
      'Content-Disposition: form-data; name=' + AnsiQuotedStr(InputFileFieldName, '"') + ';' + CRLF + 
      #9'filename=' + AnsiQuotedStr(InputFileName, '"') + CRLF +
      'Content-Type: application/octet-string' + CRLF +
      CRLF); 
    HTTP.Document.CopyFrom(InputFileData, 0); 
    WriteStrToStream(HTTP.Document,
      CRLF +
      '--' + Bound + '--' + CRLF); 
    HTTP.MimeType := 'multipart/form-data; boundary=' + Bound; 
    Result := HTTP.HTTPMethod('POST', URL); 
    if Result then 
      ResultData.LoadFromStream(HTTP.Document); 
  finally 
    HTTP.Free; 
  end; 
end; 

If you switch to Indy, you can use its TIdMultipartFormDataStream class:

function HttpPostFile(const URL, InputText1FieldName, InputText1, InputText2FieldName, InputText2, InputFileFieldName, InputFileName: string; InputFileData: TStream; ResultData: TStrings): Boolean; 
var 
  HTTP: TIdHTTP; 
  Input: TIdMultipartFormDataStream;
  Output: TMemoryStream;
begin 
  Result := False;
  try
    Output := TMemoryStream.Create;
    try
      HTTP := TIdHTTP.Create; 
      try 
        Input := TIdMultipartFormDataStream.Create;
        try
          Input.AddFormField(InputText1FieldName, InputText1);
          Input.AddFormField(InputText2FieldName, InputText2);
          Input.AddFormField(InputFileFieldName, 'application/octet-stream', '', InputFileData, InputFileName);
          HTTP.Post(URL, Input, Output);
        finally
          Input.Free;
        end;
      finally
        HTTP.Free;
      end;
      Output.Position := 0;
      ResultData.LoadFromStream(Output);
      Result := True; 
    finally
      Output.Free;
    end;
  except
  end; 
end; 


Answered By - Remy Lebeau
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing