我正在发送带有英文文件名的文件(doc,pdf,xls),但是当我发送带有希腊文件名的文件时,我正在使用服务器端?????????文件名和字符的字符错误消息Socket Error 10053,软件导致连接中止。是否有解决此类问题的方法。
代码:
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;
答案 0 :(得分:6)
Indy的默认文本编码是ASCII(因为大多数Internet协议仍然主要基于ASCII,除非它们定义额外的扩展以支持Unicode)。这就是为什么你得到?
非ASCII字符的原因。要发送非ASCII字符,您需要告诉Indy要使用的文本编码与您要交换的字符兼容。 UTF-8通常是最佳选择。有三种方法可以做到:
在GIdDefaultTextEncoding
单元中设置全局IdGlobal
变量。默认设置为encASCII
,您可以将其设置为encUTF8
:
procedure TForm1.FormCreate(Sender: TObject);
begin
GIdDefaultTextEncoding := encUTF8;
end;
将TIdIOHandler.DefStringEncoding
属性设置为TIdTextEncoding.UTF8
(如果您使用的是Indy 10.6 +,则设置为IndyTextEncoding_UTF8
):
procedure TForm1.IdTCPClient1Connected(Sender: TObject);
begin
IdTCPClient1.IOHandler.DefStringEncoding := TIdTextEncoding.UTF8;
// or:
// IdTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
end;
将TIdTextEncoding.UTF8
(或IndyTextEncoding_UTF8
)直接传递到AByteEncoding
的{{1}}参数:
WriteLn()
请记住,您使用的是Ansi的Ansi版本,IdTCPClient1.IOHandler.WriteLn(..., TIdTextEncoding.UTF8);
// or:
// IdTCPClient1.IOHandler.WriteLn(..., IndyTextEncoding_UTF8);
映射到string
,因此Indy必须先对AnsiString数据进行额外的Ansi-to-Unicode转换然后应用指定的文本编码来生成它传输的字节。通常情况下,Indy使用操作系统的默认Ansi编码来处理初始转换(因此,如果您的AnsiString
数据是希腊语编码,并且您的操作系统设置为希腊语,那么你会没问题),但是你可以使用{{1如果您需要指定AnsiString
数据使用不同的编码,则属性或TIdIOHandler.DefAnsiEncoding
的{{1}}参数。
至于你的套接字错误,没有看到导致错误的调用堆栈,或者至少代码的哪一行提升它,这很难排除故障。我的猜测是,无论ASrcEncoding
或WriteLn()
是否实际成功,都与您在AnsiString
块内调用ReadLn()
有关。该代码需要移出finally
块,它不属于那里。
尝试更像这样的东西:
WriteLn()
最后,仅仅是一个FYI,您将Write()
finally
参数设置为True,因此它将传输流大小(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;
因为{{1}之前发送AWriteByteCount
数据,然后将文件大小放在Write()
数据中是多余的。