繁体   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