Delphi 2007和更新的Indy 10

 yi品天下 发布于 2023-02-11 10:39

我正在发送带有英文文件名的文件(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通常是最佳选择.有三种方法可以做到这一点:

    GIdDefaultTextEncodingIdGlobal单元中设置全局变量.它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()数据中是多余的.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有