unit __base64;

interface

Uses
  Classes,
  NetEncoding,
  SysUTILS;

//2024.02.22; roamer55.ru

//****************************************
//Конвертировать двоичный файл в строку Base64
function File_As_StrBase64(fnIN:string): string;
//Создать двоичный файл из строки Base64
function StrBase64_As_File(fnOUT:string; S:String; YesRewrite:boolean=false): boolean;
//Создать двоичный файл из файла в формате Base64
function File_LoadFrom_Base64(fnIn64:string; fnOut:string; YesRewrite:boolean=false): boolean;
//Создать файл формата Base64 из двоичного файла
function File_SaveTo_Base64(fnIN:string; fnOut64:string; YesRewrite:boolean=false): boolean;
//Вспомогательная (возвращает размер заданного файла с именем fn)
function FileSize_Int64(fn : string) : int64;
//****************************************

implementation

function File_As_StrBase64(fnIN:string): string;
//Конвертировать двоичный файл в строку Base64
//fnIN - полное имя бинарного файла
//Возвращаемое значение - строка Base64
Var
  FileStream: TFileStream;
  Output: TStringStream;
  Encoding: TBase64Encoding;
begin
  Result:='';
  fnIN:=trim(fnIN);
  if FileExists(fnIN) then begin
     FileStream := TFileStream.Create(fnIn, fmShareDenyNone {fmCreate});
     try
       FileStream.Seek(0,soFromBeginning);
       Output:= TStringStream.Create('', TEncoding.ASCII);
       TRY
         Encoding:= TBase64Encoding.Create(0);
         TRY
           Encoding.Encode(FileStream, Output);
           Result:= Output.DataString;
         FINALLY
           Encoding.Free;
         END;
       FINALLY
         Output.Free;
       END;
     finally
       FileStream.Free;
     end;
  end;
end;

function StrBase64_As_File(fnOUT:string; S:String; YesRewrite:boolean=false): boolean;
//Создать двоичный файл из строки Base64
//fnOUT - имя результирующего (создаваемого), двоичного файла
//S - строка Base64
//YesRewrite - флаг. Если =TRUE, то файл с именем fnOUT перезапишется (если уже существует). В противном случае новый файл создан НЕ будет.
//Возвращаемое значение: результат операции ( =TRUE - успешно).
Var
  Yes:boolean;
  Input: TStringStream;
  FileStream: TFileStream;
  Encoding: TBase64Encoding;
begin
  Result:=false;
  Yes:=false;
  if S<>'' then begin
     fnOUT:=trim(fnOUT);
     if fnOUT<>'' then begin
        Yes:=true;
        if not YesRewrite then begin
           if FileExists(fnOUT) then Yes:=false;
        end
        else begin
           System.SysUtils.DeleteFile(fnOUT);
        end;
     end;
  end;
  if Yes then begin
     Input:= TStringStream.Create(S, TEncoding.ASCII);
     TRY
       FileStream := TFileStream.Create(fnOut, fmCreate);
       TRY
         Input.Position:=0;
         Encoding:= TBase64Encoding.Create(0);
         TRY
           Encoding.Decode(Input, FileStream);
           FileStream.Position:=0;
           //if FileSize_Int64(fnOUT)>0 then begin  //не факт...
              Result:=true;
           //end;
         FINALLY
           Encoding.Free;
         END;
       FINALLY
         FileStream.Free;
       END;
     FINALLY
       Input.Free;
     END;
  end;
end;

function File_LoadFrom_Base64(fnIn64:string; fnOut:string; YesRewrite:boolean=false): boolean;
//Создать двоичный файл из файла в формате Base64
//fnIn64 - имя исходного файла в формате Base64.
//fnOut - имя создаваемого двоичного файла.
//YesRewrite - флаг. Если =TRUE, то файл с именем fnOUT перезапишется (если уже существует). В противном случае новый файл создан НЕ будет.
//Возвращаемое значение: результат операции ( =TRUE - успешно).
Var
  Yes:boolean;
  List64:TStrings;
  s64:string;
begin
  Result:=false;
  Result:=false;
  Yes:=false;
  fnIn64:=trim(fnIn64);
  if FileExists(fnIn64) then begin
     fnOut:=trim(fnOut);
     if fnOut<>'' then begin
        Yes:=true;
        if not YesRewrite then begin
           if FileExists(fnOut) then Yes:=false;
        end
        else begin
           System.SysUtils.DeleteFile(fnOut);
        end;
     end;
  end;
  if Yes then begin
     List64:=TStringList.Create;
     TRY
       List64.LoadFromFile(fnIn64);
       S64:=List64.Text;
       if S64<>'' then begin
          Result:=StrBase64_As_File(fnOut, s64);
       end;
     FINALLY
       FreeAndNil(List64);
     END;
  end;
end;

function File_SaveTo_Base64(fnIN:string; fnOut64:string; YesRewrite:boolean=false): boolean;
//Создать файл формата Base64 из двоичного файла
//fnIN - имя исходного, двоичного файла
//fnOut64 - имя создаваемого файла Base64
//YesRewrite - флаг. Если =TRUE, то файл с именем fnOut64 перезапишется (если уже существует). В противном случае новый файл создан НЕ будет.
//Возвращаемое значение: результат операции ( =TRUE - успешно).
Var
  Yes:boolean;
  List64:TStrings;
  s64:string;
begin
  Result:=false;
  Yes:=false;
  fnIN:=trim(fnIN);
  if FileExists(fnIn) then begin
     fnOut64:=trim(fnOut64);
     if fnOut64<>'' then begin
        Yes:=true;
        if not YesRewrite then begin
           if FileExists(fnOut64) then Yes:=false;
        end
        else begin
           System.SysUtils.DeleteFile(fnOut64);
        end;
     end;
  end;
  if Yes then begin
     s64:=File_As_StrBase64(fnIN);
     if S64<>'' then begin
        List64:=TStringList.Create;
        TRY
          List64.Text:=S64;
          List64.SaveToFile(fnOut64);
          Result:=true;
        FINALLY
          FreeAndNil(List64);
        END;
     end;
  end;
end;

function FileSize_Int64(fn : string) : int64;
//Вспомогательная (возвращает размер заданного файла с именем fn)
Var
  SearchRec: TSearchRec;
begin
  Result:=-1;
  fn:=(fn);
  if length(fn)>0 then begin
     if FileExists(fn) then begin
        if System.SysUtils.FindFirst(fn, faAnyFile, SearchRec) = 0 then begin
           Result:=SearchRec.Size;
        end;
        System.SysUtils.FindClose(SearchRec);
     end;
  end;
end;

end.