簡體   English   中英

Delphi 2007和更新的Indy 10

[英]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通常是最佳選擇。 有三種方法可以做到這一點:

  1. IdGlobal單元中設置全局GIdDefaultTextEncoding變量。 它默認設置為encASCII ,您可以將其設置為encUTF8

     procedure TForm1.FormCreate(Sender: TObject); begin GIdDefaultTextEncoding := encUTF8; end; 
  2. 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; 
  3. 通過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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM