我正在发送带有英文文件名的文件(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;
Remy Lebeau.. 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
(或者IndyTextEncoding_UTF8
如果您使用的是Indy 10.6+):
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()
,如果您需要指定您的AnsiString
数据使用不同的编码.
至于你的套接字错误,没有看到导致错误的调用堆栈,或者至少代码的哪一行提升它,这很难排除故障.我的猜测是,它关系到你叫ReadLn()
的内部finally
块不管WriteLn()
或Write()
实际成功.该代码需要移出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,您将AWriteByteCount
参数设置Write()
为True,因此它将在发送数据之前传输流大小(Int64
因为LargeStream=True
)TStream
,因此将文件大小放在WriteLn()
数据中是多余的.