GDrive: Upload file to a specific folder

Hello,


I'm sure you can help me. In Google Drive I want to Upload a file to a specific folder like 'MyApps/AppsName/storage'. I don't want to use TMSToprage.GetDriveInfo, because if you have a large amount of files in GDrive then a lot of mega bytes will be transferred.

Thats why I created an own function to search for the folder structure. The it saves the object of the folder (CI_AppFolderGDrive) but if I want to upload a new file to this folder I get an empty "Upload error : " The log file TAdvGDrive.log says: HTTPS POST RES: 404

Would I use GDriveInfo then CI_AppFolderGDrive has a property FFolder that is not NIL. Do I use SearchFolder the property is NIL.

My question is, where is the error located in my script.

var
  CI_AppFolderGDrive : TCloudItem;

const
  cFolderGDrive = 'MyApps/AppsName/storage';

procedure Upload;
begin
  CI_AppFolderGDrive := TClouItem.Create(NIL);
  try
    FolderParts := explode('/', cFolderGDrive);
    if Length(FolderParts) = 0 then
      exit;

   CheckAndCreateFolders('', AdvGDrive, FolderParts);

   UploadedCI := AdvGDrive.Upload(CI_AppFolderGDrive, localName);
   finally
     CI_AppFolderGDrive.Free;
   end;
end;

procedure CheckAndCreateFolders(ParentFolderID : string; AdvGDrive : TAdvGDrive; FolderParts : TArray<String>; Level : integer = 0);
  var
    found: Boolean;
    i: Integer;
    fp: Integer;
    FoundCI: TCloudItem;
    FolderID : String;
  begin
    found := false;

    If AdvGDrive.SearchFolder(FolderParts[Level], true) then  // found?
    begin
      If AdvGDrive.Drive <> NIL then
        for i := 0 to AdvGDrive.Drive.Count-1 do  // Results
          If (AdvGDrive.Drive.Items.ItemType = ciFolder ) then // Result is folder
          begin
            FolderID := (AdvGDrive.Drive.Items as TGDriveItem).ID;

            // first level and parentroot or ID from father and child are the same
            If (
               ((Level = 0) and (AdvGDrive.Drive.Items as TGDriveItem).ParentRoot)
            or (ParentFolderID = (AdvGDrive.Drive.Items as TGDriveItem).ParentID)
            ) then
            begin
              // Yeah, folder found
              found := true;
              Inc(Level);

              if (Level < Length(FolderParts)) then
                // next level
                CheckAndCreateFolders( FolderID, AdvGDrive, FolderParts, Level)
              else
                CI_AppFolderGDrive.Assign(AdvGDrive.Drive.Items);
            end;
          end;
    end;

    if not found then  // if not found then create folder
    begin
      FoundCI := TCloudItem.Create(NIL);
      try
        for fp := Level to Length(FolderParts)-1 do
        begin
          FoundCI := AdvGDrive.CreateFolder(FoundCI, FolderParts[fp]);
          CI_AppFolderGDrive.Assign(FoundCI);
        end;
      finally
         FoundCI.Free;
      end;
    end;
  end;


And this is my explode function:


function explode(const separator, Str: String; limit: Integer = 0): TArray<String>;
var
  arr : TStringArray;
  Flags : TStringSplitOptions;
begin
  // TStringSplitOptions = (None, ExcludeEmpty);
  Flags := None;
  arr := TStringArray.Create();
  SetLength(arr, 1);
  arr[0] := separator;
  if limit = 0 then
    Result := Str.Split(arr, Flags)
  else
    Result := Str.Split(arr, limit, Flags);
end;


Many thanks for your help.

I'd suggest to first check if CI_AppFolderGDrive.ID is not empty and contains the unique ID for the folder where you want to upload. Retrieve one time the entire tree to get the ID and verify if the ID you retrieve via your CheckAndCreateFolders function is the same as the one with GetDriveInfo. When it is not the same, the would point in the direction that your code in CheckAndCreateFolders is incorrect.

Hi Bruno,


before I wrote the forum entry I checked the ID with output of the TAdvGDrive.log in the documents folder. And that's why I know, that it is the correct (CI as TGDriveItem).ID.

But I will learn and thats why I expand your CloudStorageDemo to show me also the (CI as TGDriveItem).ID and (CI as TGDriveItem).ParentID.

And that's correct. Your demo and my software output the same ID string, like 0B6cCY..andsoon
It has to be an other problem.

I expanded my function and now it saves the folder ID and with the next connect I use the following function. But it is the same problem.

  function CheckFolderExists(AdvGDrive : TAdvGDrive) : boolean;
  var
    GDI: TGDriveItem;
    FoundCI: TCloudItem;
    FolderID: string;
  begin
    Result := false;
    FolderID := ReadIniData(GetDBFilePath + cIniMainFile, cStr_Sec_GoogleDrive, 'FolderID');

    if trim(FolderID) = '' then exit;

    GDI := AdvGDrive.GetFileInfo(FolderID);
    if GDI = NIL then
      exit;

    if (GDI.ItemType = ciFolder) then
    FoundCI := TCloudItem.Create(NIL);
    try
      FoundCI.Assign(GDI as TCloudItem);
      CI_AppFolderGDrive.Assign(GDI as TCloudItem);  // CI_AppFolderGDrive is created in main thread
      Result := true;
    finally
      FoundCI.Free;
      GDI.Free;
    end;
  end;


Btw. I would prefer to change the property name of CI.ID to CI.No or so. It is only the file counter of the folder. And the first time (two month ago) I thougt with ID you mean this and not the real TGDriveItem.ID

Best regards
Heiko


Hello,


I did send to you a sample project where you can see the problem ;-)