unit uDlgFTPUpload;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, TFlatButtonUnit, StdCtrls, IdAntiFreezeBase, IdAntiFreeze, Zlib,
  IdMultiPartFormData, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP;

type
  TDlgFtpUpload = class(TForm)
    Label2: TLabel;
    ESpeakerName: TEdit;
    Label3: TLabel;
    ESpeakerCountry: TEdit;
    Label4: TLabel;
    ESpeakerStateRegion: TEdit;
    BtnUpload: TFlatButton;
    BtnAbort: TFlatButton;
    BtnClose: TFlatButton;
    ProgressBar1: TProgressBar;
    IdHTTP1: TIdHTTP;
    procedure BtnUploadClick(Sender: TObject);
    procedure BtnAbortClick(Sender: TObject);
    procedure BtnCloseClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
  private
    fAborted: Boolean;
    fPath: String;
    fArchiveSize: Cardinal;
    function CompressFiles(Files : TStrings; const Archivename : String): Boolean;
    function FileSize(fn: String): Integer;
    function UploadFile(Filename: String; var aAbort: Boolean): Boolean;
    function GetTempFolder: String;
  public
  end;

var
  DlgFtpUpload: TDlgFtpUpload;

implementation

{$R *.dfm}

uses ufileutils;

procedure TDlgFtpUpload.FormCreate(Sender: TObject);
begin
  fPAth:= ExtractFilePath(Application.ExeName);
  fAborted:= false;
end;

procedure TDlgFtpUpload.BtnCloseClick(Sender: TObject);
begin
  Close;
end;

procedure TDlgFtpUpload.BtnUploadClick(Sender: TObject);
var fl: TStrings;
    arcname: String;
begin
  fAborted:= false;
  fl:= nil;
  try
    try
      BtnAbort.Enabled:= true;
      BtnUpload.Enabled:= false;
      fl:= TStringList.Create;
      fl.Add('Speakername='+ESpeakerName.Text);
      fl.Add('Country='+ESpeakerCountry.Text);
      fl.Add('Region='+ESpeakerStateRegion.Text);
      fl.SaveToFile(fPath+'recorded\info.txt');
      fl.Clear;
      GetFiles(fl, fPath+'recorded\','*.*', false);
      if fl.Count < 1 then
        ShowMessage('No files found in folder "recorded"!')
      else begin
        arcname:= GetTempFolder+'v'+FormatDateTime('yymmddhhnnsszzz', now)+'.zlb';
        if CompressFiles(fl, arcname) then begin
          if UploadFile(arcname, fAborted) and not fAborted then
            MessageBox(handle, 'Upload complete!', 'PRO-ATC/X Voice Record Upload...', 0)
          else
          if not fAborted then
            MessageBox(handle, 'Error uploading file!', 'PRO-ATC/X Voice Record Upload...', 0)
        end;
      end;
    except
      on e: Exception do
        ShowMessage('Error uploading voice archive: '+e.message);
    end;
  finally
    fl.Free;
    BtnAbort.Enabled:= false;
    BtnUpload.Enabled:= true;
    ProgressBar1.Position:= 0;
    if fileexists(arcname) then
      deletefile(arcname);
    Close;
  end;
end;

function TDlgFtpUpload.FileSize(fn: String): Integer;
 var sr: TSearchRec;
begin
  if FindFirst(fn, faAnyFile, sr ) = 0 then
    result := Int64(sr.FindData.nFileSizeHigh) shl Int64(32) + Int64(sr.FindData.nFileSizeLow)
   else
    result := 0;
  FindClose(sr) ;
end;

function TDlgFtpUpload.CompressFiles(Files : TStrings; const Archivename : String): Boolean;
var infile, outfile, tmpFile: TFileStream;
    CompressedStream: TCompressionStream;
    i, l: Integer;
    s: String;
begin
  if FileExists(Archivename) then
    DeleteFile(Archivename);
  outFile:= TFileStream.Create(Archivename,fmCreate);
  try
    l:= Files.Count;
    outfile.Write(l, SizeOf(l));
    ProgressBar1.Position:= 0;
    ProgressBar1.Max:= Files.Count;
    for i:= 0 to Files.Count-1 do
    begin
      infile:= TFileStream.Create(Files[i],fmOpenRead);
      try
        { the original filename }
        s:= ExtractFilename(Files[i])+#0;
        l:= Length(s)*2;
        outfile.Write(l, SizeOf(l));
        outfile.Write(s[1], l);
        { the original filesize }
        l:= infile.Size;
        outfile.Write(l, SizeOf(l));
        { compress and store the file temporary}
        tmpFile:= TFileStream.Create('tmp',fmCreate);
        CompressedStream:= TCompressionStream.Create(clMax,tmpfile);
        try
          CompressedStream.CopyFrom(infile,l);
        finally
          CompressedStream.Free;
          tmpFile.Free;
        end;
        { append the compressed file to the destination file }
        tmpFile:= TFileStream.Create('tmp',fmOpenRead);
        try
          outfile.CopyFrom(tmpFile,0);
        finally
          tmpFile.Free;
        end;
      finally
        infile.Free;
      end;
      ProgressBar1.Position:= i;
      ProgressBar1.Invalidate;
      if i mod 20 = 0 then
        Application.ProcessMessages;
    end;
  finally
    ProgressBar1.Position:= Files.Count;
    ProgressBar1.Invalidate;
    outfile.Free;
  end;
  DeleteFile('tmp');
  result:= fileexists(Archivename);
end;

procedure DecompressFiles(const Filename, DestDirectory : String);
var
  dest,s : String;
  decompr : TDecompressionStream;
  infile, outfile : TFilestream;
  i,l,c : Integer;
begin
  // IncludeTrailingPathDelimiter (D6/D7 only)
  dest := IncludeTrailingPathDelimiter(DestDirectory);
  infile := TFileStream.Create(Filename,fmOpenRead);
  try
    { number of files }
    infile.Read(c,SizeOf(c));
    for i := 1 to c do
    begin
      { read filename }
      infile.Read(l,SizeOf(l));
      SetLength(s,l);
      infile.Read(s[1],l);
      { read filesize }
      infile.Read(l,SizeOf(l));
      { decompress the files and store it }
      s := dest+s; //include the path
      outfile := TFileStream.Create(s,fmCreate);
      decompr := TDecompressionStream.Create(infile);
      try
        outfile.CopyFrom(decompr,l);
      finally
        outfile.Free;
        decompr.Free;
      end;
    end;
  finally
    infile.Free;
  end;
end;


function TDlgFtpUpload.UploadFile(Filename: String; var aAbort: Boolean): Boolean;
var MultiPartFormDataStream: TIDMultiPartFormDataStream;
    Response: String;
begin
  result:= false;
  MultiPartFormDataStream:= nil;
  try
    try
      fArchiveSize:= FileSize(Filename);
      ProgressBar1.Position:= 0;
      ProgressBar1.Max:= fArchiveSize;
      Filename:= lowercase(filename);

      // Objekte instanzieren
      MultiPartFormDataStream := TIDMultiPartFormDataStream.Create;
      // Content-Type bestimmen
      IdHTTP1.Request.ContentType := MultiPartFormDataStream.RequestContentType;

      // Formular-Felder setzen, die keine Dateien sein sollen
      MultiPartFormDataStream.AddFormField('filename', extractfilename(filename));
      MultiPartFormDataStream.AddFile('sndfile', filename, '');
      MultiPartFormDataStream.Position := 0;
      Response := IdHTTP1.Post('http://www.fsatc.net/phpu/sndupload.php', MultiPartFormDataStream);
      result:= trim(Response)='E=0';
    except
      beep;
    end;
  finally
    MultiPartFormDataStream.Free;
  end;
end;

procedure TDlgFtpUpload.BtnAbortClick(Sender: TObject);
begin
  if MessageDlg('Sure you want to abort uploading?', mtConfirmation, [mbyes, mbno], 0) = mryes then begin
    fAborted:= true;
    if IdHTTP1.Connected then IdHTTP1.Disconnect;
  end;
end;


procedure TDlgFtpUpload.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  ProgressBar1.Position:= AWorkCount;
  Application.ProcessMessages;
end;

function TDlgFtpUpload.GetTempFolder: String;
var tempFolder: array[0..MAX_PATH] of Char;
begin
  GetTempPath(MAX_PATH, @tempFolder);
  result := IncludeTrailingPathDelimiter(String(tempFolder));
  if length(result) < 3 then
    raise Exception.Create('Unable to locate temp folder.');
end;


end.
