环境:delphi7.0
使用IdFtp上传文件,如何实现续传?
IdFTP1.Put('c:\aa.exe','aa.exe',true);
使用这条命令,如果是一次就传完,没有问题;但是中断之后,再上传,字节数就不对,不知是怎么回事?

解决方案 »

  1.   

    server你写得吗?要自己让server支持断点
      

  2.   

    是单位的Ftp服务,支持断点续传。不知是不是Idftp上传文件不支持断点续传?举个例子说吧:要上传的文件aa.exe大小为4M,我用IdFTP1.Put('c:\aa.exe','aa.exe',true)先上传了1M,然后中断,那么就还剩3M未上传,接着又用IdFTP1.Put('c:\aa.exe','aa.exe',true)命令继续上传,上传完成后,服务器上的文件大小却成了5M,感觉象是:除了先前传1M外,又在后累加了4M,具体该怎么做,谢谢!
      

  3.   

    呵呵
    你需要修改Indy的源码
    APPE是可以续传的,但必须保证你的Stream的Position移动到断点的位置,Indy默认是0,当然就错误了
    REST方法也是可以,但必须发送断点信息到服务器,这个看RFC959协议吧修改Indy源码是麻烦的了,自己尝试做吧另外Indy的上传过程有时候会导致UI没有反应的,放在独立线程中就可以解决这个问题能说的就这些的,剩下的自己研究吧_____________________
    http://lysoft.7u7.net
      

  4.   

    谢谢你的回复,看得出你的见解精辟,我试了用APPE,容易出现异常,不知改Indy的源码,应该怎么做?或者用Rest,该怎么做?谢谢
      

  5.   

    IdFTP.pas文件,InternalGet中添加if AResume then begin
                  Self.SendCmd('REST ' + IntToStr(ADest.Position), [350]);   {Do not translate}
                end;
    而:
    procedure TIdFTP.Get(const ASourceFile, ADestFile: string; const ACanOverwrite: boolean = false;
      AResume: Boolean = false);
    var
      LDestStream: TFileStream;
    begin
      if FileExists(ADestFile) then begin
        AResume := AResume and CanResume;
        if ACanOverwrite and (not AResume) then begin
          LDestStream := TFileStream.Create(ADestFile, fmCreate);
        end
        else begin
          if (not ACanOverwrite) and AResume then begin
            LDestStream := TFileStream.Create(ADestFile, fmOpenReadWrite);
            LDestStream.Seek(0, soFromEnd);
          end
          else begin
            raise EIdFTPFileAlreadyExists.Create(RSDestinationFileAlreadyExists);
          end;
        end;
      end
      else begin
        LDestStream := TFileStream.Create(ADestFile, fmCreate);
      end;  try
        Get(ASourceFile, LDestStream, AResume);
      finally
        FreeAndNil(LDestStream);
      end;
    end剩下的靠自己,就只能说那么多的_____________________
    http://lysoft.7u7.net
      

  6.   

    ly_liuyang(Liu Yang) :你所给的代码是下载的,上传的该怎么改呢?
      

  7.   

    procedure TIdFTP.Put(const ASourceFile: string; const ADestFile: string = '';
     const AAppend: boolean = false; const Resume: boolean = false);
    var                            // resume mode --- by Liu Yang 2002.1.31
      LSourceStream: TFileStream;
    begin
      LSourceStream := TFileStream.Create(ASourceFile, fmOpenRead or fmShareDenyNone);
      // resume upload --- by Liu Yang 2002.1.31
      if ResumeSupported and Resume
         then begin
                FResumeUpload := True;
                FResumePoint := Size(ADestFile);
              end
         else FResumeUpload:=false;
      // fixed end
      try Put(LSourceStream, ADestFile, AAppend); finally FreeAndNil(LSourceStream); end;
    end;_____________________
    http://lysoft.7u7.net
      

  8.   

    还有这个部分:procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string = '';
     const AAppend: boolean = false; const Resume: boolean = false);
    var z: TZDataStream;
    begin     
      // resume upload --- by Liu Yang 2002.1.31
      if ResumeSupported and Resume
         then begin
                FResumeUpload := True;
                FResumePoint := Size(ADestFile);
              end
         else FResumeUpload:=false;
      // added 'MODE Z' support --- by Liu Yang 2005.5.9
      if mzUpload in ModeZ then
         begin
           SendModeZ;
           z := TZDataStream.Create(zctCompress, ASource);
           try
           z.UseActualSize := True;
           if Length(ADestFile) = 0 then begin
             InternalPut('STOU ' + ADestFile, z);
           end else if AAppend then begin
             InternalPut('APPE ' + ADestFile, z);
           end else begin
             InternalPut('STOR ' + ADestFile, z);
           end;
           finally
           z.Free;
           end;
           Exit;
         end else if ModeZ <> [] then SendModeS;
      if Length(ADestFile) = 0 then begin
        InternalPut('STOU ' + ADestFile, ASource);
      end else if AAppend then begin
        InternalPut('APPE ' + ADestFile, ASource);
      end else begin
        InternalPut('STOR ' + ADestFile, ASource);
      end;
    end;_____________________
    http://lysoft.7u7.net
      

  9.   

    Indy不仅支持下载断点续传,也支持上载断点续传,而且不需要对Indy做出改造。
    在Blues的blog,他提到可以“通过IDFTP得到服务端已经上传的部分的SIZE,然后通过文件流在本地建立剩余部分的临时文件,然后以 APPEND方式上传,传完后删除临时文件,达到上传断点续传的效果”。原文在此:DELPHI ftp 上传断点续传的实现。
    我再仔细看了Indy的源码,发现不需要临时文件。可以对Blues的方法作出重大改进:
    Put()方法第一个参数可以是TStream(实际上,如果是文件名的话Indy会建立Stream,然后再调用Stream的Put方法)。而且如果 Append设为True的话,Indy不会去动Stream的Position:   1. procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string = '';
       2.  const AAppend: boolean = false);
       3. ...
       4. procedure TIdTCPConnection.WriteStream(AStream: TStream; const AAll: boolean = true;
       5.   const AWriteByteCount: Boolean = False; const ASize: Integer = 0);
       6. ...
       7.   if AAll then begin //bianbian注:如果Append,AAll是false
       8.     AStream.Position := 0;
       9.   end;
      10.   // This is copied to a local var because accessing .Size is very inefficient
      11.   if ASize = 0 then begin
      12.     LStreamEnd := AStream.Size;
      13.   end else begin
      14.     LStreamEnd := ASize + AStream.Position;
      15.   end;
      16.   LSize := LStreamEnd - AStream.Position;
      17. ...也就是说,先把原文件的Stream Seek到Size位置,丢给Indy即可,实现也很简单:   1. var
       2.   fs: TFileStream;
       3. ...
       4.   fs := TFileStream.Create(FullFileName, fmOpenRead or fmShareDenyWrite);
       5.   fs.Seek(size, 0); //偏移
       6.   FTP.Put(fs, ExtractFileName(FullFileName), True);
       7.   fs.Free;