msgraph-sdk-java: Getting file from drive doesn't return @microsoft.graph.downloadUrl property

Hi. I’m trying to get file information and then content.

File info :

So, I’m doing next call : String request = String.format("/sites/%s/drives/%s/root:/%s", siteId, driveId, filePath); JsonObject obj = graphClient.customRequest(request).buildRequest().get(); And getting 404 : Not found. But file is there. So I downloaded Microsoft Graph Postman collection and tried to get file info there, by calling same API and I got the file. So I started to dig and found that in Microsoft Graph Postman collection they are using header : Prefer=apiversion=2.1 So I removed that header in postman and also there got “Item not found”.

When I did : List<HeaderOption> headers = new ArrayList<>(); headers.add(new HeaderOption("Prefer", "apiversion=2.1")); String request = String.format("/sites/%s/drives/%s/root:/%s", siteId, driveId, filePath); JsonObject obj = graphClient.customRequest(request).buildRequest().get();

I got file info. But, when I’m changing request to get file content it’ works fine without Prefer header: String request = String.format("/sites/%s/drives/%s/root:/%s:/content", siteId, driveId, filePath); BufferedInputStream is = graphClient.customRequest(request, BufferedInputStream.class) .buildRequest().get(); And I getting stream with file content.

So first question what is this header and why without it I can’t find file ?

File content :

I got file info but it doesn’t contains @microsoft.graph.downloadUrl field in it: { “@odata.context”: “https://graph.microsoft.com/v1.0/$metadata#sites(‘domain.sharepoint.com%2Ccc767111-*%2Cc0ef7f82-*’)/drives(‘b"k4l2zKLNsk62Log2MF8UIBtTYFV’)/root/$entity”, “cTag”: “"c:{0e8182ec-5ee9-41e6-96ba-372340f873cb},1"”, “createdBy”: { “user”: { “displayName”: “Slava”, “email”: “slava@domain.onmicrosoft.com”, “id”: “1bf721e3-d0f7-4238-88a9-7e13f22efa01” } }, “createdDateTime”: “2020-03-22T20:29:23Z”, “eTag”: “"{0E8182EC-5EE9-41E6-96BA-372340F873CB},1"”, “file”: { “hashes”: { “quickXorHash”: “cwjdhie41VYT6k3bdKT/y30bKX0=” }, “mimeType”: “application/pdf” }, “fileSystemInfo”: { “createdDateTime”: “2020-03-22T20:29:23Z”, “lastModifiedDateTime”: “2020-03-22T20:29:23Z” }, “id”: “01J7TAN47MQKAQ52K64ZAZNORXENAPQ46L”, “lastModifiedBy”: { “user”: { “displayName”: “Slava”, “email”: “slava@domain.onmicrosoft.com”, “id”: “1bf721e3-d0f7-4238-88a9-7e13f22efa01” } }, “lastModifiedDateTime”: “2020-03-22T20:29:23Z”, “name”: “A Survey of Applications of Markov Decision Processes.pdf”, “parentReference”: { “driveId”: “b%22k4l2zKLNsk62Log2MF8UIBtTYFV”, “driveType”: “documentLibrary”, “id”: “01J7TAN123Y2GOVW7725BZO354PWSELRRZ”, “path”: “/drives/b%22k4l2zKLNsk62Log2MF8UIBtTYFV/root:” }, “size”: 6590404, “webUrl”: “https://domain.sharepoint.com/sites/Test/Shared Documents/A Survey of Applications of Markov Decision Processes.pdf” }

So, to get download URL I need to call to call GET http call to /sites/{site-id}/drive/root:/{item-path}:/content Then I’m getting 302 response with Location header with the URL, so now to be able to get content from Sharepoint file and validate that file downloaded is fine (using hash), I need to do 3 calls , first to get all file metadata, then call to get Location URL and then real call to get a content.

Why @microsoft.graph.downloadUrl is not returned in the call ?

Thanks

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 20 (1 by maintainers)

Most upvoted comments

It was an implementation option that was not pursued - unfortunately the only way to see the “system” drives is to use the select syntax.

Sorry 😃

The site enumeration system doesn’t actually have the webid for the root web, but the site identifiers support falling back to the root web if only one GUID is provided, so:

domain.sharepoint.com,cc767993-*

is equivalent to:

domain.sharepoint.com,cc767993-*,5560531b-*

in the case where 5560531b-* is the id of the root web.

And yes, it will only return the root webs and so if you need to discover all the sub-webs for a site you’d need to query each in turn.

You found the right approach for discovering the other types of “drives”, and I agree that it’s not standard. The intent when we came up with those semantics was to allow an “enlightened” application to query for data that isn’t returned by default. There were three ways to do that:

  1. Use a filter
  2. select
  3. Add a prefer header value

Using a filter kinda made sense, but it still had the problem that it’s a little strange because you’d have to have a filter like filter=system eq null or system ne null to say you want everything. A preference would have been unambiguous but would have required clients to have full control over the headers they provide, which is not always true for all OData frameworks. So we landed on select with intention being that if you ask for system that implies you know what it means and we can safely return the values that would have otherwise been hidden.

If we start over would we do it this way again? Probably not, but it’s unfortunately part of the contract now.

That’s actually, somewhat misleadingly, documenting how you can find the root site collections in the tenant (I.e. how you can discover the various geo locations in which a tenant resides). That’s why it’s documenting the specific filter and select statements that must be required.

I’ll update this issue tomorrow once I’ve had a chat with the team.