Jump to content
Updated RadStudio RoadMap Read more... ×
chkaufmann

Indy - TIdMultiPartFormDataStream

Recommended Posts

For a HTTP Post request I create a TIdMultiPartFormDataStream and then I use AddFormField() to put my values. Now I noticed, that "=" is replaced by "=3D" and Content-Transfer-Encoding is set to "quoted-printable".

 

Using the $_POST[] variable in my PHP script, the 3D remains and I get wrong results. Now I'm not sure where I should change that? Should the request be without Content-Transfer-Encoding? or with a different one?

Or should I change my PHP script and expect a "quoted-printable" string? I didn't find any information for PHP if I can get the Content-Transfer-Encoding from somewhere. I always thought PHP does handle such things automatically.

 

Christian

Share this post


Link to post
Posted (edited)

I usually use this kind of code:

 

StringStream := TStringStream.Create(Params, TEncoding.UTF8);
try
  Result := FIdHTTP.Post('http://abc.de/my/service/', StringStream);
finally
  StringStream.Free;
end;

In the above code, I set this property for the FIdHTTP object:

 

//Set the Content-Type
FIdHTTP.Request.CustomHeaders.AddValue('Content-Type', 'application/x-www-form-urlencoded');

 

And here's how the variable Params looks like:

 

Params := 'id=1&name=test';

 

Server-side, the values can be easily saved with this code:

 

 $id = $_POST["id"]  //this is '1'
 $name = $_POST["name"]  //this is 'test'

 

Is there a better way? Yes, for sure. I don't know what's the best approach but this is the solution that I usually use to send POST requests via program. It works well

Edited by Alberto Miola

Share this post


Link to post
3 hours ago, chkaufmann said:

For a HTTP Post request I create a TIdMultiPartFormDataStream and then I use AddFormField() to put my values. Now I noticed, that "=" is replaced by "=3D" and Content-Transfer-Encoding is set to "quoted-printable".

Yes, text fields are encoded using MIME's "quoted-printable" format by default.  You can use the TIdFormDataField.ContentTransfer property to change the encoding.  Supported values are: a blank string (7-bit US-ASCII without sending a 'Content-Transfer-Encoding' header), '7bit', '8bit', 'binary', 'quoted-printable', and 'base64'.

3 hours ago, chkaufmann said:

Using the $_POST[] variable in my PHP script, the 3D remains and I get wrong results.

I would consider that to be a bug in PHP, if it is not decoding the MIME encoding that is declared in the posted data.  In this case, I would suggest setting the TIdFormDataField.ContentTransfer to '8bit' to send the text data in its raw charset form.  For instance, this is actually required if you want to send text data in UTF-8.

 

Funny, I just answered a similar question on StackOverflow just this morning: Delphi Indy Post Encoding and PHP.

3 hours ago, chkaufmann said:

Now I'm not sure where I should change that? Should the request be without Content-Transfer-Encoding? or with a different one?

Usually a different one.  If no ContentTransfer is specified, US-ASCII is used, which will lose data if the text has non-ASCII characters in it.

3 hours ago, chkaufmann said:

Or should I change my PHP script and expect a "quoted-printable" string?

"quoted-printable" is part of the MIME standard.  All MIME implementations are required to support it.  However, RFC 7578 deprecates the use of the 'Content-Transfer-Encoding' header in 'multipart/form-data' submissions over HTTP, but TIdMultipartFormDataStream has not been updated to account for that yet.

3 hours ago, chkaufmann said:

I didn't find any information for PHP if I can get the Content-Transfer-Encoding from somewhere. I always thought PHP does handle such things automatically.

See https://bugs.php.net/bug.php?id=48219

Share this post


Link to post
34 minutes ago, Alberto Miola said:

I usually use this kind of code:

 


StringStream := TStringStream.Create(Params, TEncoding.UTF8);
try
  Result := FIdHTTP.Post('http://abc.de/my/service/', StringStream);
finally
  StringStream.Free;
end;

In the above code, I set this property for the FIdHTTP object:

 


//Set the Content-Type
FIdHTTP.Request.CustomHeaders.AddValue('Content-Type', 'application/x-www-form-urlencoded');

You should not use the Request.CustomHeaders property to set the 'Content-Type' header, use the Request.ContentType property instead.  And the official way to send an 'application/x-www-form-urlencoded' post with TIdHTTP is to use the overloaded version of the TIdHTTP.Post() method that takes a TStrings as input, not the overload that takes a TStream as input.  The TStrings overload takes a list of 'name=value' strings and posts them in 'application/x-www-form-urlencoded' format for you.

34 minutes ago, Alberto Miola said:

Is there a better way? Yes, for sure.

Absolutely.  See above.

34 minutes ago, Alberto Miola said:

this is the solution that I usually use to send POST requests via program. It works well

You are using the wrong approach and should update your code to let TIdHTTP do the hard work for you.  Especially in regards to how the 'name=value' strings get formatted.  TIdHTTP follows the HTML5 standard in that regard, which saves you the trouble of having to deal with it manually.

  • Thanks 1

Share this post


Link to post

Thanks Remy. I set the type to '8bit' and all works fine now, even when post variables contain cyrillic characters.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×