bas
bas

Reputation: 15462

Get link to file in shared onedrive folder where file isn't directly shared

I'm working on a onedrive integration in my app. The idea is that users that have the onedrive file explorer client installed can drag a file and the app is able to generate a link to the file online.

I've pretty much implemented it but there is one situation that I can't get working.

For regular onedrive files I use:

RESTRequest1.Resource := Format('/me/drive/root:/%s:/createLink', [RelativePath]); 

And for shared files I use

RESTRequest1.Resource := '/me/drive/sharedWithMe';

And then I loop through shared files until I find matching file and then I grab the webUrl from the response.

The problem is this though. There is a folder shared with me and for this folder I added a shortcut to the shared folder in my OneDrive like described here. One of the files in this folder is also shared directly with me, the other one isn't. The file that's shared directly with me I can find using /me/drive/sharedWithMe. But I'm not able to retrieve the file that isn't shared directly with me. It is in the shared folder though so I thought I should be able to.

I tried some different things like looking if I could get the shared folder by calling this: /me/drive/root/children. But this gives me all folders and files except for the shared folder.

Is it possible what I'm trying to do?

Upvotes: 1

Views: 184

Answers (2)

bas
bas

Reputation: 15462

I was able to figure something out.

Like I mentioned in my question I had tried this endpoint: /me/drive/root/children. But this gives me all folders and files except for the shared folder.

I found something interesting in the response when I tried this endpoint: me/drive/root. The response contained: "folder":{"childCount":7}. 7 is the correct number of files and folders in the root onedrive directory including the shortcut to the shared folder.

I find it strange that this endpoint shows the correct count, but that the children endpoint does not get the shared folder, but either way because of this I did try to get info on the shared folder directly with this endpoint: /me/drive/root:/NameSharedFolder:/ and that actually worked. Got back something like this:

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)/$entity",
  "createdBy": {
    "application": {
      "id": "id",
      "displayName": "SharePoint Online Client Extensibility"
    },
    "user": {
      "email": "email",
      "id": "id",
      "displayName": "displayname"
    }
  },
  "createdDateTime": "2025-02-17T09:26:14Z",
  "eTag": "\"{tag},3\"",
  "id": "id",
  "lastModifiedBy": {
    "user": {
      "email": "email",
      "id": "id",
      "displayName": "displayName"
    }
  },
  "lastModifiedDateTime": "2025-02-17T09:26:15Z",
  "name": "NameSharedFolder",
  "parentReference": {
    "driveType": "business",
    "driveId": "driveID",
    "id": "id",
    "name": "Documents",
    "path": "/drive/root:",
    "siteId": "siteID"
  },
  "cTag": "\"c:{tag},1\"",
  "fileSystemInfo": {
    "createdDateTime": "2025-02-17T09:26:14Z",
    "lastModifiedDateTime": "2025-02-17T09:26:15Z"
  },
  "remoteItem": {
    "folder": {
      "childCount": 2
    },
    "id": "id",
    "parentReference": {
      "driveType": "business",
      "driveId": "driveID"
    },
    "sharepointIds": {
      "listId": "id",
      "listItemUniqueId": "id",
      "siteId": "id",
      "siteUrl": "id",
      "webId": "id",
      "webRelativeListUrl": "Documents"
    },
    "size": 31810
  },
  "size": 0
}

From this I could get the driveID and folderID (id) and do a request to /drives/{drive-id}/items/{item-id}/children. The response of this request listed the file with webUrl.

This is the delphi code that gives me the file link:


  RESTRequest1.Resource := '/me/drive/root:/' + ExtractFileDir(RelativePath) + ':/';
  RESTRequest1.Method := rmGET;
  RESTRequest1.Params.Clear;
  RESTRequest1.Execute;

  if RestRequest1.Response.StatusCode = 200 then
  begin
    var sharedFolder := TJSONObject.ParseJSONValue(RestRequest1.Response.Content) as TJSONObject;
    try
      if sharedFolder.Values['remoteItem'] <> nil then
      begin
        var remoteItem := sharedFolder.Values['remoteItem'] as TJSONObject;
        folderID := remoteItem.GetValue<string>('id');
        driveID := TJSONObject(remoteItem.GetValue('parentReference')).GetValue<string>('driveId');
      end else
      begin
        folderID := sharedFolder.GetValue<string>('id');
        driveID := TJSONObject(sharedFolder.Values['parentReference']).GetValue<string>('driveId');
      end;
    finally
      sharedFolder.Free;
    end;

    RESTRequest1.Resource := '/drives/' + driveID + '/items/' + folderID + '/children';
    RESTRequest1.Method := rmGET;
    RESTRequest1.Params.Clear;
    RESTRequest1.Execute;

    if RestRequest1.Response.StatusCode = 200 then
    begin
      var sharedFolderItems := TJSONObject.ParseJSONValue(RestRequest1.Response.Content) as TJSONObject;
      try
        var sharedFolderItemsArray := sharedFolderItems.GetValue<TJSONArray>('value');
        var fileName := ExtractFileName(RelativePath);
        for var I := 0 to sharedFolderItemsArray.Count - 1 do
        begin
          var item := sharedFolderItemsArray.Items[I] as TJSONObject;
          if SameText(item.GetValue<string>('name'), fileName) then
          begin
            var webURL := item.GetValue<string>('webUrl'); // Got webURL do something with it...
            Break;
          end;
        end;
      finally
        sharedFolderItems.Free;
      end;
    end;
  end;

Upvotes: 1

Marc Wittmann
Marc Wittmann

Reputation: 2671

As I see it you try to query the files in your onedrive (either shared by you or with you). But if it is a shared file you do not always have the file availabe in you own onedrive. It is rather a shortcut to the file (although you don`t see that), where the files resides in the original owners onedrive.

/me/drive/root/children API call will not return shortcuts to shared folders

/me/drive/sharedWithMe should only return files and folders explicitly shared with you directly

So you might need to query the "Special" Collection for Shortcuts which is provided by the api:

https://graph.microsoft.com/v1.0/me/drive/special/shortcuts/children (Http Get)

With the shortcut folder found, you can query its children:

https://graph.microsoft.com/v1.0/me/drive/items/{shortcut-folder-id}/children (Http Get)

But maybe it would be better to get a link to the original file in another owners onedrive.

https://graph.microsoft.com/v1.0/drives/{ownerDriveId}/items/{sharedFolderId}/children

I am not sure though if the information received by the special folder query is sufficient for that.

Upvotes: 1

Related Questions