unit uSubirFicheros; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, uROClient, uROClientIntf, uRORemoteService, uROBinMessage, uROServiceComponent, uROWinInetHttpChannel, VARELA_Intf, uROTypes; type { TROThread } TSubirFicheroThread = class(TThread) private fROMessage: TROBinMessage; fROChannel: TROWinInetHTTPChannel; fRORemoteService: TRORemoteService; fOnAbort: TNotifyEvent; fOnFinished: TNotifyEvent; fOnProgress: TNotifyEvent; fOnStartUpload: TNotifyEvent; fOnError: TNotifyEvent; fFileName: string; fUploadOK: Boolean; fFileSize: Int64; fCurrentBytePos: Int64; fTimeStarted: TDateTime; fFileService: IsrvTransfereciaFicheros; fErrorText: string; fInfoStr: string; fMaxConnectionErrors, fChannelErrorscount: Integer; procedure RunUpload; function GetUploadChunk(FileMemStream: TMemoryStream; aSize: Int64; const Sequence: Integer): Binary; procedure OnChannelFailure(Sender: TROTransportChannel; anException: Exception; var Retry: Boolean); procedure Run; protected public property UploadOK: Boolean read fUploadOK; property FileSize: Int64 read fFileSize; property CurrentBytePos: Int64 read fCurrentBytePos; property TimeStarted: TDateTime read fTimeStarted; property ErrorText: string read fErrortext; property Filename: string read fFilename; property InfoStr: string read fInfoStr; constructor Create(aFileName: string; aOnStartUpload, aOnProgress, aOnFinished, aOnAbort, aOnError: TNotifyEvent); destructor Destroy; override; procedure Execute; override; end; implementation uses uDataModuleBase; { TROThread } constructor TSubirFicheroThread.Create(aFileName: string; aOnStartUpload, aOnProgress, aOnFinished, aOnAbort, aOnError: TNotifyEvent); begin inherited Create(TRUE); fFilename := aFilename; fmaxconnectionerrors := 5; //try 5 times on channel-error fROMessage := TROBinMessage.Create(nil); fROChannel := TROWinInetHTTPChannel.Create(NIL); fROChannel.OnFailure := OnChannelFailure; fROChannel.TargetURL := dmBase.Channel.TargetURL; fRORemoteService := TRORemoteService.Create(nil); fRORemoteService.Channel := fROChannel; fRORemoteService.Message := fROMessage; fRORemoteService.ServiceName := 'srvTransfereciaFicheros'; fFileService := fRORemoteService as IsrvTransfereciaFicheros; if assigned(aOnAbort) then fOnAbort := aOnAbort; if assigned(aOnFinished) then fOnFinished := aOnFinished; if assigned(aOnProgress) then fOnProgress := aOnProgress; if assigned(aOnStartUpload) then fOnStartUpload := aOnStartUpload; if assigned(aOnError) then fOnError := aOnError; Resume; end; destructor TSubirFicheroThread.Destroy; begin fFileService := nil; fROChannel.OnFailure := NIL; FreeAndNil(fRORemoteService); FreeAndNil(fROChannel); FreeAndNil(fROMessage); inherited; end; procedure TSubirFicheroThread.Run; begin try RunUpload; finally if assigned(fOnFinished) then fOnFinished(Self); end; end; procedure TSubirFicheroThread.Execute; begin try Run; finally Self.Destroy; end; end; function TSubirFicheroThread.GetUploadChunk(FileMemStream: TMemoryStream; aSize: Int64; const Sequence: Integer): Binary; const Block: Integer = 65536; var Position: Int64; begin Result := Binary.Create; Position := Block * (Sequence - 1); if Position <= aSize then begin FileMemStream.Position := Position; if Position + Block > aSize then Result.CopyFrom(FileMemStream, aSize - Position) else Result.CopyFrom(FileMemStream, Block); end; end; procedure TSubirFicheroThread.RunUpload; var FileMemStream: TMemoryStream; Chunk: Binary; Sequence: Int64; isfirst: Boolean; begin fErrorText := ''; fUploadOK := false; fChannelErrorscount := 0; fCurrentBytePos := 0; Sequence := 1; fTimeStarted := Now; FileMemStream := nil; isfirst := true; try if FileExists(fFilename) then begin try FileMemStream := TMemoryStream.Create; FileMemStream.LoadFromFile(fFileName); fFileName := ExtractFileName(fFileName); fFileSize := FileMemStream.Size; fInfoStr := DateTimetoStr(fTimeStarted) + ' ' + fFileName + ' ' + FloatToStrF(Filesize / 1024, fffixed, 15, 1) + ' KB'; if assigned(fOnStartUpload) then fOnStartUpload(Self); Chunk := GetUploadChunk(FileMemStream, fFileSize, Sequence); try while Chunk.Size > 0 do begin if Terminated then begin if assigned(fOnAbort) then fOnAbort(Self); exit; end; fFileService.uploadChunk(isfirst, fFileName, Chunk); isfirst := false; Inc(fCurrentBytePos, Chunk.Size); FreeAndNil(Chunk); Inc(Sequence); if assigned(fOnProgress) then fOnProgress(Self); Chunk := GetUploadChunk(FileMemStream, fFileSize, Sequence); end; fUploadOK := (FileSize > 0) and (FileSize = CurrentBytePos); finally FreeAndNil(Chunk); end; finally FileMemStream.Free; end; end else begin fErrorText := 'No existe el fichero ' + fFileName; if assigned(fOnError) then fOnError(Self); end; except on e: Exception do begin fErrorText := e.Message; if assigned(fOnError) then fOnError(Self); end; end; end; procedure TSubirFicheroThread.OnChannelFailure(Sender: TROTransportChannel; anException: Exception; var Retry: Boolean); begin if FChannelErrorsCount > FMaxConnectionErrors then begin FErrorText := anException.Message; Self.Terminate; end else begin Inc(FChannelErrorsCount); Sleep(1000); Retry := true; end; end; end.