Search code examples
delphitcpclientindy

Send file to website with Indy TIdTCPClient


I need the right way to send a file with TIdTCPClient to the top4top website.

I send it with the WriteFile() option in TIdTCPClient but it does not work, and send with a stream but I get a bad request.

var
  utf8: IIdTextEncoding;
  sid,result: string;
  lParam: TIdMultiPartFormDataStream;
begin
  sid := 'Z2jAmKM%2CA8Ik2dJxlR9NlZUW65b';
  if OpenDialog1.Execute then
  begin
    utf8 := IndyTextEncoding_UTF8;
    lParam := TIdMultiPartFormDataStream.Create;
    lParam.AddFormField('sid', sid);
    lParam.AddFile('file_1_', OpenDialog1.FileName);
    lParam.AddFormField('submitr', '[ رفع الملفات ]');
    TCPC.host := 'up.top4top.net';
    TCPC.Port := 443;
    TCPC.ConnectTimeout := 100000;
    TCPC.ReadTimeout := 500000;
    TCPC.Connect;
    TCPC.Socket.WriteLn('POST /index.php HTTP/1.1');
    TCPC.Socket.WriteLn('Host: up.top4top.net');
    TCPC.Socket.WriteLn('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
    TCPC.Socket.WriteLn('Accept-Encoding: gzip, deflate, br');
    TCPC.Socket.WriteLn('Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7');
    TCPC.Socket.WriteLn('Content-Type: multipart/form-data; boundary=----   WebKitFormBoundarySSk63dIh0HIAto8S');
    TCPC.Socket.WriteLn('DNT: 1');
    TCPC.Socket.WriteLn('Origin: https://up.top4top.net');
    TCPC.Socket.WriteLn('Referer: https://up.top4top.net/');
    TCPC.Socket.WriteLn('Upgrade-Insecure-Requests: 1');
    TCPC.Socket.WriteLn('User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64)  AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36   OPR/57.0.3098.106');
    TCPC.Socket.Write(lParam);
    TCPC.Socket.WriteLn('');
    Result := TCPC.Socket.AllData(utf8);
    TCPC.Disconnect;
  end;

Solution

  • You are making several mistakes:

    1. The value of the boundary attribute you are specifying in the Content-Type header does not match what TIdMultiPartFormDataStream actually uses when encoding its MIME data. You need to use the TIdMultiPartFormDataStream.RequestContentType property to set the Content-Type header properly. Otherwise the server will not parse the data correctly.

    2. you are not sending a Content-Length header at all. The server needs to be told how much data you are sending.

    3. your call to WriteLn('') needs to be before the call to Write(lParam), not after. An HTTP message's headers and body are separated by a blank line.

    Try this instead:

    var
      sid, result: string;
      lParam: TIdMultiPartFormDataStream;
    begin
      sid := 'Z2jAmKM%2CA8Ik2dJxlR9NlZUW65b';
      if OpenDialog1.Execute then
      begin
        lParam := TIdMultiPartFormDataStream.Create;
        try
          lParam.AddFormField('sid', sid);
          lParam.AddFile('file_1_', OpenDialog1.FileName);
          lParam.AddFormField('submitr', '[ رفع الملفات ]', 'utf-8');
    
          TCPC.Host := 'up.top4top.net';
          TCPC.Port := 443;
          TCPC.ConnectTimeout := 100000;
          TCPC.ReadTimeout := 500000;
    
          // make sure you have an SSLIOHandler component
          // assigned to the TCPC.IOHandler property, and
          // its PassThrough property is set to False before
          // sending any data...
          TCPC.Connect;
          try
            // set PassThrough=False here if not already...
    
            TCPC.Socket.WriteLn('POST /index.php HTTP/1.1');
            TCPC.Socket.WriteLn('Host: up.top4top.net');
            TCPC.Socket.WriteLn('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
            TCPC.Socket.WriteLn('Accept-Encoding: gzip, deflate, br');
            TCPC.Socket.WriteLn('Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7');
            TCPC.Socket.WriteLn('Connection: close');
            TCPC.Socket.WriteLn('Content-Type: ' + lParam.RequestContentType);
            TCPC.Socket.WriteLn('Content-Length: ' + IntToStr(lParam.Size));
            TCPC.Socket.WriteLn('DNT: 1');
            TCPC.Socket.WriteLn('Origin: https://up.top4top.net');
            TCPC.Socket.WriteLn('Referer: https://up.top4top.net/');
            TCPC.Socket.WriteLn('Upgrade-Insecure-Requests: 1');
            TCPC.Socket.WriteLn('User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 OPR/57.0.3098.106');
            TCPC.Socket.WriteLn;
            TCPC.Socket.Write(lParam);
    
            Result := TCPC.Socket.AllData(IndyTextEncoding_UTF8);
          finally
            TCPC.Disconnect;
          end;
        finally
          lParam.Free;
        end;
      end;
      ...
    end;