[英]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.