View Issue Details

IDProjectCategoryView StatusLast Update
0027558FPCFCLpublic2019-12-05 16:05
ReporterAndrewH Assigned ToMichael Van Canneyt  
PrioritynormalSeverityminorReproducibilityhave not tried
Status resolvedResolutionfixed 
Product Version3.1.1 
Target Version3.2.0Fixed in Version3.1.1 
Summary0027558: [PATCH] TFPCustomHTTPClient.FileFormPost add possiblilty to include formdata and file in same POST request
DescriptionAdded procedure StreamFormPost and overloaded FileFormPost to allow adding Formdata when sending a file.

Before you could send formdata (name=value pairs) or a file (field-name filename)
Now you can do both with FileFormPost or StreamFormPost in the same POST request
TagsNo tags attached.
Fixed in Revision30123
FPCOldBugId0
FPCTarget-
Attached Files

Activities

AndrewH

2015-02-27 20:58

developer  

fcl-web-form-and-stream.diff (3,531 bytes)   
Index: packages/fcl-web/src/base/fphttpclient.pp
===================================================================
--- packages/fcl-web/src/base/fphttpclient.pp	(revision 30024)
+++ packages/fcl-web/src/base/fphttpclient.pp	(working copy)
@@ -202,6 +202,12 @@
     Class function SimpleFormPost(const URL: string; FormData : TStrings): String;
     // Post a file
     Procedure FileFormPost(const AURL, AFieldName, AFileName: string; const Response: TStream);
+    // Post form with a file
+    Procedure FileFormPost(const AURL: string; FormData: TStrings; AFieldName, AFileName: string; const Response: TStream);
+    // Post a stream
+    Procedure StreamFormPost(const AURL, AFieldName, AFileName: string; const AStream: TStream; const Response: TStream);
+    // Post form with a stream
+    Procedure StreamFormPost(const AURL: string; FormData: TStrings; const AFieldName, AFileName: string; const AStream: TStream; const Response: TStream);
     // Simple form of Posting a file
     Class Procedure SimpleFileFormPost(const AURL, AFieldName, AFileName: string; const Response: TStream);
   Protected
@@ -420,7 +426,7 @@
     Result:=Result+'?'+URI.Params;
 end;
 
-Function TFPCustomHTTPClient.GetSocketHandler(Const UseSSL : Boolean) : TSocketHandler;
+function TFPCustomHTTPClient.GetSocketHandler(const UseSSL: Boolean): TSocketHandler;
 
 begin
   Result:=Nil;
@@ -1708,25 +1714,56 @@
 
 procedure TFPCustomHTTPClient.FileFormPost(const AURL, AFieldName,
   AFileName: string; const Response: TStream);
+begin
+  FileFormPost(AURL, nil, AFieldName, AFileName, Response);
+end;
 
+procedure TFPCustomHTTPClient.FileFormPost(const AURL: string;
+  FormData: TStrings; AFieldName, AFileName: string; const Response: TStream);
+var
+  F: TFileStream;
+begin
+  F:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
+  StreamFormPost(AURL, FormData, AFieldName, ExtractFileName(AFileName), F, Response);
+  F.Free;
+end;
+
+procedure TFPCustomHTTPClient.StreamFormPost(const AURL, AFieldName,
+  AFileName: string; const AStream: TStream; const Response: TStream);
+begin
+  StreamFormPost(AURL, nil, AFieldName, AFileName, AStream, Response);
+end;
+
+procedure TFPCustomHTTPClient.StreamFormPost(const AURL: string;
+  FormData: TStrings; const AFieldName, AFileName: string;
+  const AStream: TStream; const Response: TStream);
 Var
   S, Sep : string;
   SS : TStringStream;
-  F : TFileStream;
+  I: Integer;
+  N,V: String;
 begin
   Sep:=Format('%.8x_multipart_boundary',[Random($ffffff)]);
   AddHeader('Content-Type','multipart/form-data; boundary='+Sep);
+  SS:=TStringStream.Create('');
+  if FormData <> nil then
+    for I := 0 to FormData.Count -1 do
+    begin
+      // not url encoded
+      FormData.GetNameValue(I,N,V);
+      S :='--'+Sep+CRLF;
+      S:=S+Format('Content-Disposition: form-data; name="%s"'+CRLF+CRLF+'%s'+CRLF,[N, V]);
+      SS.WriteBuffer(S[1],Length(S));
+    end;
   S:='--'+Sep+CRLF;
   s:=s+Format('Content-Disposition: form-data; name="%s"; filename="%s"'+CRLF,[AFieldName,ExtractFileName(AFileName)]);
   s:=s+'Content-Type: application/octet-string'+CRLF+CRLF;
-  SS:=TStringStream.Create(s);
+  SS.WriteBuffer(S[1],Length(S));
   try
-    SS.Seek(0,soFromEnd);
-    F:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
     try
-      SS.CopyFrom(F,F.Size);
+      AStream.Seek(0, soFromBeginning);
+      SS.CopyFrom(AStream,AStream.Size);
     finally
-      F.Free;
     end;
     S:=CRLF+'--'+Sep+'--'+CRLF;
     SS.WriteBuffer(S[1],Length(S));
fcl-web-form-and-stream.diff (3,531 bytes)   

Michael Van Canneyt

2015-03-07 17:13

administrator   ~0081704

Your patch contained 2 potential memory leaks, fixed those and then applied the patch. Thanks for implementing it !

Issue History

Date Modified Username Field Change
2015-02-27 20:58 AndrewH New Issue
2015-02-27 20:58 AndrewH File Added: fcl-web-form-and-stream.diff
2015-02-27 20:59 AndrewH Description Updated View Revisions
2015-02-27 21:23 Jonas Maebe Assigned To => Michael Van Canneyt
2015-02-27 21:23 Jonas Maebe Status new => assigned
2015-03-07 17:13 Michael Van Canneyt Fixed in Revision => 30123
2015-03-07 17:13 Michael Van Canneyt Note Added: 0081704
2015-03-07 17:13 Michael Van Canneyt Status assigned => resolved
2015-03-07 17:13 Michael Van Canneyt Fixed in Version => 3.1.1
2015-03-07 17:13 Michael Van Canneyt Resolution open => fixed
2015-03-07 17:13 Michael Van Canneyt Target Version => 4.0.0
2019-12-05 16:05 Michael Van Canneyt Target Version 4.0.0 => 3.2.0
2019-12-05 16:05 Michael Van Canneyt FPCTarget => -