加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 如何使用IndyFtpServer(v10)限制检索文件的速度

发布时间:2020-12-15 04:25:12 所属栏目:大数据 来源:网络整理
导读:我正在使用Delphi XE 6和Indy10开发FTP服务器.问题是我需要限制下载速度(必须是可配置的Ex.1 KB / s,1 MB / s等)并且我不能使它工作.我知道像BitsPerSec等道具,但这只会影响协议数据交换,而不会影响与RETR命令的文件交换.我在IdFTPServer.pass中看到,并且Str
我正在使用Delphi XE 6和Indy10开发FTP服务器.问题是我需要限制下载速度(必须是可配置的Ex.1 KB / s,1 MB / s等)并且我不能使它工作.我知道像BitsPerSec等道具,但这只会影响协议数据交换,而不会影响与RETR命令的文件交换.我在IdFTPServer.pass中看到,并且Stream被转换为字符串并使用repeat / until循环发送(使用IOHandler.Write())但我需要某种形式的控制上传/下载过程并且能够限制速度所有传入客户端连接.请帮忙实现这一目标吗?

PD:抱歉我的英语不好.

我尝试使用以下代码为RETR命令实现CommandHandler:

procedure TForm1.IdFTPServer1CommandHandlers0Command(ASender: TIdCommand);
var
  LContext : TIdFTPServerContext;
  vStream: TFileStream;
  path: String;
  vX: Integer;
  LEncoding: IIdTextEncoding;
begin

  LEncoding := IndyTextEncoding_8Bit;
  LContext := ASender.Context as TIdFTPServerContext;
  path := 'D:indy_in_depth.pdf';


  try
    vStream := TFileStream.Create(path,fmOpenRead);
    //LContext.DataChannel.FtpOperation := ftpRetr;
    //LContext.DataChannel.Data := VStream;
    LContext.DataChannel.OKReply.SetReply(226,RSFTPDataConnClosed);
    LContext.DataChannel.ErrorReply.SetReply(426,RSFTPDataConnClosedAbnormally);

    ASender.Reply.SetReply(150,RSFTPDataConnToOpen);
    ASender.SendReply;

    Memo1.Lines.Add('Sending a file with: ' + IntToStr(vStream.Size) + ' bytes');
    //Make control of speed here !
    for vX := 1 to vStream.Size do
      begin
        vStream.Position := vX;
        LContext.Connection.IOHandler.Write(vStream,1,False);
        if vX mod 10000 = 0 then
          Memo1.Lines.Add('Sended byte: ' + IntToStr(vX));
      end;

    //LContext.DataChannel.InitOperation(False);

    //LContext.Connection.IOHandler.Write(vStream);

    //LContext.KillDataChannel;
    LContext.Connection.Socket.Close;

    VStream.Free;
  except
    on E: Exception do
    begin
      ASender.Reply.SetReply(550,E.Message);
    end;
  end;

end;

但Filezilla FTP客户端显示流数据,就像其他命令的一部分.

Filezilla Client

解决方法

The problem is that i need to limit the speed of download (must be configurable Ex. 1 KB/s,1 MB/s,etc.) and i don’t make it work. I know some props like BitsPerSec,etc. but this only affect the protocol data exchange,not the file exchange with RETR command.

BitsPerSec是TIdInterceptThrottler类的属性(以及RecvBitsPerSec和SendBitsPerSec属性).可以通过其Intercept属性将该类的实例分配给任何TIdTCPConnection对象.这不仅限于命令连接,它也可以用于传输连接.

您可以通过TIdFTPServerContext.DataChannel.FDataChannel成员访问TIdFTPServer中文件传输的TIdTCPConnection对象,例如在OnRetrieveFile事件中:

type
  // the TIdDataChannel.FDataChannel member is 'protected',// so use an accessor class to reach it...
  TIdDataChannelAccess = class(TIdDataChannel)
  end;

procedure TForm1.IdFTPServer1RetrieveFile(ASender: TIdFTPServerContext;
  const AFileName: TIdFTPFileName; var VStream: TStream);
var
  Conn: TIdTCPConnection;
begin
  Conn := TIdDataChannelAccess(ASender.DataChannel).FDataChannel;
  if Conn.Intercept = nil then
    Conn.Intercept := TIdInterceptThrottler.Create(Conn);
  TIdInterceptThrottler(Conn.Intercept).BitsPerSec := ...;
  VStream := TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
end;

另一种方法是创建自己的T(File)Stream派生类,以覆盖虚拟的Read()和Write()方法,根据需要执行自己的限制,然后将该类的实例分配给OnRetrieveFile的VStream参数,OnStoreFile事件.

I see in IdFTPServer.pas,and the Stream is converted to string and send with a repeat/until loop (with IOHandler.Write())

不,流不会转换为字符串.你误读了代码.在对IOHandler.Write(TStream)方法的单个调用中,流的内容将作为二进制数据原样发送.

but i need some form of control the upload/download process and be able to limit the speed for all incoming client connections.

往上看.

I try to implement a CommandHandler for the RETR command

您不应该直接处理RETR命令. TIdFTPServer已经为您做到了这一点.您打算使用OnRetrieveFile事件来准备下载,并使用OnStoreFile事件进行上载.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读