DELPHI ftp 断点续传(indy)
By:Roy.LiuLast updated:2009-02-17
Indy不仅支持下载断点续传,也支持上载断点续传,而且不需要对Indy做出改造。
在Blues的blog,他提到可以“通过IDFTP得到服务端已经上传的部分的SIZE,然后通过文件流在本地建立剩余部分的临时文件,然后以APPEND方式上传,传完后删除临时文件,达到上传断点续传的效果”。原文在此:DELPHI ftp 上传断点续传的实现(http://www.beginlove.net/blog/article.asp?id=172)。
我再仔细看了Indy的源码,发现不需要临时文件。可以对Blues的方法作出重大改进:
Put()方法第一个参数可以是TStream(实际上,如果是文件名的话Indy会建立Stream,然后再调用Stream的Put方法)。而且如果Append设为True的话,Indy不会去动Stream的Position:
procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string = '';
const AAppend: boolean = false);
...
procedure TIdTCPConnection.WriteStream(AStream: TStream; const AAll: boolean = true;
const AWriteByteCount: Boolean = False; const ASize: Integer = 0);
...
if AAll then begin //bianbian注:如果Append,AAll是false
AStream.Position := 0;
end;
// This is copied to a local var because accessing .Size is very inefficient
if ASize = 0 then begin
LStreamEnd := AStream.Size;
end else begin
LStreamEnd := ASize + AStream.Position;
end;
LSize := LStreamEnd - AStream.Position;
...
也就是说,先把原文件的Stream Seek到Size位置,丢给Indy即可,实现也很简单:
var
fs: TFileStream;
...
fs := TFileStream.Create(FullFileName, fmOpenRead or fmShareDenyWrite);
fs.Seek(size, 0); //偏移
FTP.Put(fs, ExtractFileName(FullFileName), True);
fs.Free;
在Blues的blog,他提到可以“通过IDFTP得到服务端已经上传的部分的SIZE,然后通过文件流在本地建立剩余部分的临时文件,然后以APPEND方式上传,传完后删除临时文件,达到上传断点续传的效果”。原文在此:DELPHI ftp 上传断点续传的实现(http://www.beginlove.net/blog/article.asp?id=172)。
我再仔细看了Indy的源码,发现不需要临时文件。可以对Blues的方法作出重大改进:
Put()方法第一个参数可以是TStream(实际上,如果是文件名的话Indy会建立Stream,然后再调用Stream的Put方法)。而且如果Append设为True的话,Indy不会去动Stream的Position:
procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string = '';
const AAppend: boolean = false);
...
procedure TIdTCPConnection.WriteStream(AStream: TStream; const AAll: boolean = true;
const AWriteByteCount: Boolean = False; const ASize: Integer = 0);
...
if AAll then begin //bianbian注:如果Append,AAll是false
AStream.Position := 0;
end;
// This is copied to a local var because accessing .Size is very inefficient
if ASize = 0 then begin
LStreamEnd := AStream.Size;
end else begin
LStreamEnd := ASize + AStream.Position;
end;
LSize := LStreamEnd - AStream.Position;
...
也就是说,先把原文件的Stream Seek到Size位置,丢给Indy即可,实现也很简单:
var
fs: TFileStream;
...
fs := TFileStream.Create(FullFileName, fmOpenRead or fmShareDenyWrite);
fs.Seek(size, 0); //偏移
FTP.Put(fs, ExtractFileName(FullFileName), True);
fs.Free;
From:一号门
Previous:XML导入SQL
Next:jface中对话框返回数据给调用窗口
COMMENTS