delphi – 如何使用IndyFtpServer(v10)限制检索文件的速度
我正在使用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 解决方法
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事件.
不,流不会转换为字符串.你误读了代码.在对IOHandler.Write(TStream)方法的单个调用中,流的内容将作为二进制数据原样发送.
往上看.
您不应该直接处理RETR命令. TIdFTPServer已经为您做到了这一点.您打算使用OnRetrieveFile事件来准备下载,并使用OnStoreFile事件进行上载. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |