[英]Delphi 2007 & Updated Indy 10
我正在发送带有英文文件名的文件(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;
Indy的默认文本编码是ASCII(因为大多数Internet协议仍主要基于ASCII,除非它们定义额外的扩展以支持Unicode)。 这就是你得到的原因?
对于非ASCII字符。 要发送非ASCII字符,您需要告诉Indy要使用的文本编码与您要交换的字符兼容。 UTF-8通常是最佳选择。 有三种方法可以做到这一点:
在IdGlobal
单元中设置全局GIdDefaultTextEncoding
变量。 它默认设置为encASCII
,您可以将其设置为encUTF8
:
procedure TForm1.FormCreate(Sender: TObject); begin GIdDefaultTextEncoding := encUTF8; end;
将TIdIOHandler.DefStringEncoding
属性设置为TIdTextEncoding.UTF8
(如果使用的是Indy IndyTextEncoding_UTF8
则设置为TIdIOHandler.DefStringEncoding
):
procedure TForm1.IdTCPClient1Connected(Sender: TObject); begin IdTCPClient1.IOHandler.DefStringEncoding := TIdTextEncoding.UTF8; // or: // IdTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8; end;
通过TIdTextEncoding.UTF8
(或IndyTextEncoding_UTF8
直接地)到AByteEncoding
的参数WriteLn()
IdTCPClient1.IOHandler.WriteLn(..., TIdTextEncoding.UTF8); // or: // IdTCPClient1.IOHandler.WriteLn(..., IndyTextEncoding_UTF8);
请记住,您使用的是Ansi版本的Delphi,其中string
映射到AnsiString
,因此Indy必须对AnsiString数据执行额外的Ansi-to-Unicode转换,然后才能应用指定的文本编码来生成字节数传输。 通常,Indy使用操作系统的默认Ansi编码来处理初始转换(因此,如果您的AnsiString
数据是希腊语编码,并且您的操作系统设置为希腊语,那么您会没问题),但是您可以使用TIdIOHandler.DefAnsiEncoding
属性,或者ASrcEncoding
WriteLn()
ASrcEncoding
参数,如果您需要指定您的AnsiString
数据使用不同的编码。
至于你的套接字错误,没有看到导致错误的调用堆栈,或者至少代码的哪一行提升它,这很难排除故障。 我的猜测是,无论WriteLn()
或Write()
实际上是否成功,它都与你在finally
块中调用ReadLn()
有关。 该代码需要移出finally
块,它不属于那里。
尝试更像这样的东西:
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;
最后,只是一个FYI,您将Write()
的AWriteByteCount
参数设置为True,因此它将传输流大小(因为LargeStream=True
而作为Int64
),然后发送TStream
数据,因此放入文件大小在WriteLn()
数据中是多余的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.