WoN*_*DeR 6 delphi ftp indy ftp-server
我正在使用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;
Run Code Online (Sandbox Code Playgroud)
但Filezilla FTP客户端显示流数据,就像其他命令的一部分.
Rem*_*eau 12
问题是我需要限制下载速度(必须是可配置的Ex.1 KB/s,1 MB/s等)并且我不能使它工作.我知道一些道具等
BitsPerSec,但这只影响协议数据交换,而不是文件与RETR命令交换.
BitsPerSec是的一个属性TIdInterceptThrottler类(连同RecvBitsPerSec和SendBitsPerSec属性).可以TIdTCPConnection通过其Intercept属性将该类的实例分配给任何对象.这不仅限于命令连接,它也可以用于传输连接.
您可以通过该成员访问TIdTCPConnection文件传输的对象,例如:TIdFTPServerTIdFTPServerContext.DataChannel.FDataChannelOnRetrieveFile
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;
Run Code Online (Sandbox Code Playgroud)
另一种方法是创建自己的T(File)Stream派生类来覆盖虚拟Read()和Write()方法,以根据需要执行自己的限制,然后将该类的实例分配给和事件的VStream参数.OnRetrieveFileOnStoreFile
我看到了
IdFTPServer.pas,并且Stream被转换为字符串并使用repeat/until循环发送(使用IOHandler.Write())
不,流不会转换为字符串.你误读了代码.在对IOHandler.Write(TStream)方法的单个调用中,流的内容将作为二进制数据原样发送.
但我需要某种形式的控制上传/下载过程,并能够限制所有传入客户端连接的速度.
往上看.
我尝试为RETR命令实现CommandHandler
你不应该直接处理RETR命令. 已经为你做了.您打算使用该事件来准备下载,以及上传事件.TIdFTPServerOnRetrieveFileOnStoreFile
| 归档时间: |
|
| 查看次数: |
184 次 |
| 最近记录: |