德尔福2007&更新了Indy 10

时间:2013-12-12 21:25:54

标签: delphi delphi-2007 indy10

我正在发送带有英文文件名的文件(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;

1 个答案:

答案 0 :(得分:6)

Indy的默认文本编码是ASCII(因为大多数Internet协议仍然主要基于ASCII,除非它们定义额外的扩展以支持Unicode)。这就是为什么你得到?非ASCII字符的原因。要发送非ASCII字符,您需要告诉Indy要使用的文本编码与您要交换的字符兼容。 UTF-8通常是最佳选择。有三种方法可以做到:

  1. GIdDefaultTextEncoding单元中设置全局IdGlobal变量。默认设置为encASCII,您可以将其设置为encUTF8

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      GIdDefaultTextEncoding := encUTF8;
    end;
    
  2. 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;
    
  3. TIdTextEncoding.UTF8(或IndyTextEncoding_UTF8)直接传递到AByteEncoding的{​​{1}}参数:

    WriteLn()
  4. 请记住,您使用的是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}}参数。

    至于你的套接字错误,没有看到导致错误的调用堆栈,或者至少代码的哪一行提升它,这很难排除故障。我的猜测是,无论ASrcEncodingWriteLn()是否实际成功,都与您在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()数据中是多余的。