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;
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
GIdDefaultTextEncodingvariable in theIdGlobalunit. It is set toencASCIIby default, you can set it toencUTF8instead:set the
TIdIOHandler.DefStringEncodingproperty toTIdTextEncoding.UTF8(orIndyTextEncoding_UTF8if you are using Indy 10.6+):pass
TIdTextEncoding.UTF8(orIndyTextEncoding_UTF8) directly to theAByteEncodingparameter ofWriteLn():Keep in mind that you are using an Ansi version of Delphi, where
stringmaps toAnsiString, 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 yourAnsiStringdata is Greek encoded, and your OS is set to Greek, you will be fine), however you can use theTIdIOHandler.DefAnsiEncodingproperty, or theASrcEncodingparameter ofWriteLn(), if you need to specify that yourAnsiStringdata 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 thefinallyblock regardless of whetherWriteLn()orWrite()actually succeeded. That code needs to be moved out of thefinallyblock, it does not belong there.Try something more like this instead:
Lastly, just an FYI, you are setting the
AWriteByteCountparameter ofWrite()to True, so it is going to transmit the stream size (as anInt64because ofLargeStream=True) before then sending theTStreamdata, so putting the file size in theWriteLn()data is redundant.