小7的大店铺【淘宝店】 游戏引擎剖析-全篇 公积金相关帖子汇总 魅族M8SDK学习系列不断更新中

[Delphi] Indy实现FTP上传下载,支持断点续传

[ 3677 查看 / 0 回复 ]

这两天一直在研究Indy的TIdFTP,用来实现FTP操作。 完整的代码请到此下载http://www.mini188.com/showtopic-855.aspx 因为是Delphi7自带的,好像有许多 BUG,使用时也确实是这样,总是有些奇怪的问题出现。但简单的功能还是实现了。使用他的Put和Get方法可以完成基本的操作。 简单代码如下: 下载代码
  1. //下载,支持断点续传
  2. procedure TForm1.Button5Click(Sender: TObject);
  3. var
  4.   stream: TFileStream;
  5.   sDownToFileName: string;
  6.   bIsDir: Boolean;
  7.   sDir: string;
  8. begin
  9.   if ListView1.Selected = nil then Exit;
  10.   if not IdFTP1.Connected then
  11.     raise Exception.Create('未连接FTP服务器');

  12.   if SaveDialog1.Execute then
  13.   begin
  14.     sDownToFileName := SaveDialog1.FileName;
  15.     if FileExists(sDownToFileName) then
  16.       stream := TFileStream.Create(sDownToFileName, fmOpenWrite)
  17.     else
  18.       stream := TFileStream.Create(sDownToFileName, fmCreate);
  19.     try
  20.       if ListView1.Items.Count > 0 then //ListView1是从FTP服务器取的当前目录列表
  21.       begin
  22.         sDir := GetNameFromDirLine(FFtpDirList.Strings[ListView1.ItemIndex], bIsDir);//取得当前选中的是否为文件
  23.         if not bIsDir then
  24.         begin
  25.           pb1.Max := IdFTP1.Size(sDir);//pb1是ProgressBar控件,进度条
  26.           pb1.Position := stream.Size;
  27.           stream.Position := stream.Size;//如果本地文件存在将位置移动到尾部
  28.           IdFTP1.Get(sDir, stream, True);//这个不就说了 吧,最后一个参数使用True就表明是支续传
  29.           ChageDir(IdFTP1.RetrieveCurrentDir);
  30.         end;
  31.       end;
  32.     finally
  33.       FreeAndNil(stream);
  34.     end;
  35.   end;
  36. end;

  37. function TForm1.GetNameFromDirLine(Line: string; var IsDirectory: Boolean): string;
  38. var
  39.   i: Integer;
  40.   DosListing: Boolean;
  41. begin
  42.   IsDirectory := Line[1] = 'd';
  43.   DosListing := false;
  44.   for i := 0 to 7 do begin
  45.     if (i = 2) and not IsDirectory then
  46.     begin
  47.       //IsDirectory := Copy(Line, 1, Pos(' ', Line) - 1) = '<DIR>';
  48.       IsDirectory := Copy(Line, 1, Pos(' ', Line) - 1) = '<DIR>';
  49.       if not IsDirectory then
  50.         DosListing := Line[1] in ['0'..'9']
  51.       else
  52.         DosListing := true;
  53.     end;
  54.     Delete(Line, 1, Pos(' ', Line));
  55.     While Line[1] = ' ' do Delete(Line, 1, 1);
  56.     if DosListing and (i = 2) then break;
  57.   end;
  58.   Result := Line;
  59. end;
复制代码
上传的代码
  1. procedure TForm1.PutFile(const AFileName: string);
  2. var
  3.   mm: TFileStream;
  4.   iFileSize: Int64;
  5. begin
  6.   mm := TFileStream.Create(AFileName, fmOpenRead);
  7.   try
  8.     pb1.Max := mm.Size;
  9.     iFileSize := IdFTP1.Size(ExtractFileName(AFileName));
  10.     if iFileSize <> -1 then// 如果不是-1表明服务器上有同名文件,则需要续传
  11.     begin
  12.       pb1.Position := iFileSize;
  13.       mm.Position := iFileSize;
  14.       IdFTP1.Quote('REST ' + FloatToStr(iFileSize));
  15.       IdFTP1.Put(mm, ExtractFileName(AFileName), True);//最后一个参数就是打开Append,这样可以不重新上传文件了
  16.     end
  17.     else
  18.       IdFTP1.Put(mm, ExtractFileName(AFileName));

  19.     ChageDir(IdFTP1.RetrieveCurrentDir);
  20.   finally
  21.     FreeAndNil(mm);
  22.   end;
  23. end;
复制代码
上面的代码只是简单的实现了上传和下载,在测试过程中下载比较顺利,但是上传时如果中途中断了操作会报一个异常。必须断开连接重新连接上后再传就可以了。 在Delphi2009中也测试了一下新版本的Indy,发现有个更郁闷的问题,IdFTP.List读取过来的中文都是乱码。也不知道是为什么,看代码应该是字符编码问题,但不知道如何解决。更新了字符编码也无用。
最后编辑5207 最后编辑于 2008-12-17 19:53:33
本主题由 皇帝 5207 于 2009-7-3 22:59:21 执行 主题分类 操作
分享 转发
相信与不相信都是矛盾的.  5207宣!
欢迎您来到迷你论坛
TOP