Delphi 2007 & Updated Indy 10

delphi, delphi-2007, indy10

Solution

Indy's default text encoding is ASCII (because the majority of Internet protocols are still largely ASCII based, unless they define extra extensions to support Unicode). That is why you are getting `?` for non-ASCII characters. To send non-ASCII characters, you need to tell Indy which text encoding to use that is compatible with the characters you are exchanging. UTF-8 is usually the best choice for that. There are three ways you can do that:

set the global `GIdDefaultTextEncoding` variable in the `IdGlobal` unit. It is set to `encASCII` by default, you can set it to `encUTF8` instead:

procedure TForm1.FormCreate(Sender: TObject);
begin
  GIdDefaultTextEncoding := encUTF8;
end;

set the `TIdIOHandler.DefStringEncoding` property to `TIdTextEncoding.UTF8` (or `IndyTextEncoding_UTF8` if you are using Indy 10.6+):

procedure TForm1.IdTCPClient1Connected(Sender: TObject);
begin
  IdTCPClient1.IOHandler.DefStringEncoding := TIdTextEncoding.UTF8;
  // or:
  // IdTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
end;

pass `TIdTextEncoding.UTF8` (or `IndyTextEncoding_UTF8`) directly to the `AByteEncoding` parameter of `WriteLn()`:

IdTCPClient1.IOHandler.WriteLn(..., TIdTextEncoding.UTF8);
// or:
// IdTCPClient1.IOHandler.WriteLn(..., IndyTextEncoding_UTF8);

Keep in mind that you are using an Ansi version of Delphi, where `string` maps to `AnsiString`, and thus Indy has to perform an additional Ansi-to-Unicode conversion of AnsiString data before it can then apply the specified text encoding to produce the bytes it transmits. Typically, Indy uses the OS's default Ansi encoding to handle that initial conversion (so if your `AnsiString` data is Greek encoded, and your OS is set to Greek, you will be fine), however you can use the `TIdIOHandler.DefAnsiEncoding` property, or the `ASrcEncoding` parameter of `WriteLn()`, if you need to specify that your `AnsiString` data is using a different encoding.

As for your socket error, without seeing a call stack leading up to the error, or at least which line of your code is raising it, that is difficult to troubleshoot. My guess is that it is related to you calling `ReadLn()` inside of the `finally` block regardless of whether `WriteLn()` or `Write()` actually succeeded. That code needs to be moved out of the `finally` block, it does not belong there.

Try something more like this instead:

procedure TForm1.LoadFileButtonClick(Sender: TObject);
begin
  OpenDialog1.Filter := 'All Files (*.*)';
  OpenDialog1.FilterIndex := 1; 
  if OpenDialog1.Execute then
  begin
    Edit1.Text := ExtractFileName(OpenDialog1.FileName); 
    Edit3.Text := OpenDialog1.FileName; 

    // Indy has its own FileSizeByName() function...
    Edit2.Text := IntToStr(FileSizeByName(OpenDialog1.FileName));
  end;
end;

procedure TForm1.SendFileButtonClick(Sender: TObject);
var
  IncommingText: string;
  Strm: TFileStream;
begin
  if not CheckBox1.Checked then
  begin
    ShowMessage('Please connect to the Server');
    Exit;
  end;
  if OpenDialog1.FileName = '' then
  begin
    ShowMessage('Please choose a file');
    Exit;
  end;
  Strm := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
  try
    IdTCPClient1.IOHandler.WriteLn(Edit1.Text + '@' + Edit2.Text + ';' + Edit3.Text + ',', TIdTextEncoding.UTF8);
    IdTCPClient1.IOHandler.LargeStream := True;
    IdTCPClient1.IOHandler.Write(Strm, 0 , True);
  finally
    Strm.Free;
  end;
  Memo1.Lines.Add('File Sent');
  IncommingText := IdTCPClient1.IOHandler.ReadLn; 
  if IncommingText = 'DONE!' then begin 
    Memo1.Lines.Add('File ' + Edit1.Text + ' ' + Edit2.Text + ' was received successfully by the Server');
    //APPLICATION.ProcessMessages;
  end else
  begin
    Memo1.Lines.Add('File ' + Edit1.Text + ' was not received by the Server');
  end;
end;

Lastly, just an FYI, you are setting the `AWriteByteCount` parameter of `Write()` to True, so it is going to transmit the stream size (as an `Int64` because of `LargeStream=True`) before then sending the `TStream` data, so putting the file size in the `WriteLn()` data is redundant.

Problem

I am sending alright files (doc, pdf, xls) with english filenames but when I am sending files with greek filenames I am getting on server side ????????? characters for filename & the error message Socket Error 10053, software caused connection abort. Is there a solution for this kind of problem. Code: ``` procedure TForm1.LoadFileButtonClick(Sender: TObject); begin OpenDialog1.Filter := 'All Files (*.*)'; OpenDialog1.FilterIndex := 1; if OpenDialog1.Execute then begin Edit1.Text := ExtractFileName(OpenDialog1.FileName); Edit3.Text := OpenDialog1.FileName; Fstream := TFileStream.Create(OpenDialog1.FileName, fmopenread); Edit2.Text := inttostr(Fstream.Size); Fstream.Position := 0; FreeandNil(FStream); //Fstream.Free; end; end; procedure TForm1.SendFileButtonClick(Sender: TObject); var IncommingText: string; begin if (opendialog1.filename<>'') and (CheckBox1.Checked = True) then begin IdTCPClient1.iohandler.writeln(edit1.text + '@' + edit2.text + ';' + edit3.text + ','); Sleep(2000); try IdTCPClient1.IOHandler.largestream:=true; Fstream := TFileStream.Create(OpenDialog1.FileName, fmopenread); IdTCPClient1.IOHandler.Write(Fstream, 0 ,true); finally Fstream.Position := 0; FreeandNil(FStream); //Fstream.Free; memo1.Lines.Add('File Sent'); IncommingText := IdTCPClient1.iohandler.readln; if IncommingText = 'DONE!' then begin Memo1.Lines.Add('File ' +Edit1.Text +' ' +Edit2.Text +' was received successfully by the Server'); //APPLICATION.ProcessMessages; end else begin Memo1.Lines.Add('File ' +Edit1.Text +' was not received by the Server'); end; end; //try - finally end else begin showmessage('Please choose a file Or Try to connect to the Server'); end; end; ```

Original source