12

I have a simple php script on my web server which I need to upload a file using HTTP POST, which I am doing in Delphi.

Here is my code with Indy but aparantely it won't work and I can't figure out what i am not doing properly. How can I view what I send on the server is there such a tool ?

procedure TForm1.btn1Click(Sender: TObject);
var
  fname : string;
  MS,dump : TMemoryStream;
  http  : TIdHTTP;

const
  CRLF = #13#10;
begin
  if PromptForFileName(fname,'','','','',false) then
  begin
    MS := TMemoryStream.Create();
    MS.LoadFromFile(fname);
    dump := TMemoryStream.Create();
    http := TIdHTTP.Create();
    http.Request.ContentType:='multipart/form-data;boundary =-----------------------------7cf87224d2020a';
    fname := CRLF + '-----------------------------7cf87224d2020a' + CRLF + 'Content-Disposition: form-data; name=\"uploadedfile\";filename=\"test.png"' + CRLF;
    dump.Write(fname[1],Length(fname));
    dump.Write(MS.Memory^,MS.Size);
    fname := CRLF + '-----------------------------7cf87224d2020a--' + CRLF;
    dump.Write(fname[1],Length(fname));
    ShowMessage(IntToStr(dump.Size));
    MS.Clear;
    try
    http.Request.Method := 'POST';
    http.Post('http://posttestserver.com/post.php',dump,MS);
    ShowMessage(PAnsiChar(MS.Memory));
    ShowMessage(IntToStr(http.ResponseCode));
    except
    ShowMessage('Could not bind socket');
    end;
  end;
end;
Warren P
  • 65,725
  • 40
  • 181
  • 316
opc0de
  • 11,557
  • 14
  • 94
  • 187
  • 2
    "It doesn't work" is the least useful phrase possible when debugging something. What doesn't work? What does it do wrong? – Mason Wheeler May 26 '12 at 11:03
  • @MasonWheeler if i knew the answer probably i was not asking this question . It doesn't upload to the webserver that is the problem my guess that the post header is malformed but I don't know what I am doing wrong. – opc0de May 26 '12 at 11:05
  • why is MS.Clear; called before http.Post( URL, MS )? –  May 26 '12 at 11:22
  • 1
    So you get no error messages or anything, just silently fails? That's what Doesn't Work means. Otherwise say "I get this error code" or whatever. – Warren P May 26 '12 at 14:49

3 Answers3

21

Indy has TIdMultipartFormDataStream for this purpose:

procedure TForm1.SendPostData;
var
  Stream: TStringStream;
  Params: TIdMultipartFormDataStream;
begin
  Stream := TStringStream.Create('');
  try
   Params := TIdMultipartFormDataStream.Create;
   try
    Params.AddFile('File1', 'C:\test.txt','application/octet-stream');
    try
     HTTP.Post('http://posttestserver.com/post.php', Params, Stream);
    except
     on E: Exception do
       ShowMessage('Error encountered during POST: ' + E.Message);
    end;
    ShowMessage(Stream.DataString);
   finally
    Params.Free;
   end;
  finally
   Stream.Free;
  end;
end;
whosrdaddy
  • 11,720
  • 4
  • 50
  • 99
  • 1
    Use wireshark and compare the header produced by your code and Indy?? – whosrdaddy May 28 '12 at 15:19
  • Its so obvious of course `TIdMultipartFormDataStream` is the upload a file component I've been looking for how did I miss it ? :) – Toby Allen Feb 26 '13 at 15:11
  • @TobyAllen: Learning something new every day is part of a developer's career :) – whosrdaddy Feb 26 '13 at 15:46
  • fyi, for anyone not familiar with php or indy: File1 in this example is the name of variable for your $_FILES[""] in php. Took me a while to figure that out! Thanks for the good answer. – Aaron Jun 21 '13 at 15:48
2

Calling a PHP from Indy can fail because of the User-Agent, then you get 403 error.

Try this way, it fixed it for me:

var Answer: string;
begin
  GetHTML:= TIdHTTP.create(Nil);
  try
    GetHTML.Request.UserAgent:= 'Mozilla/3.0';
    Answer:= GetHTML.Get('http://www.testserver.com/test.php?id=1');
  finally
    GetHTML.Free;
  end;
end;
-1

You lost 2 characters '--'. It is better to do so:

http.Request.ContentType:='multipart/form-data;boundary='+myBoundery;
fname := CRLF + '--' + myBoundery + CRLF + 'Content-Disposition: form-data; name=\"uploadedfile\";filename=\"test.png"' + CRLF;