1

I try to download several files from OneDrive through Microsoft Graph.

I am very close to achieve my goal. For the moment I have managed the token system (notably through Jay Lee detailed answer), and achieved to resolve the confusion that I made among the different endpoints that exist in Microsoft Graph (thank you Marc LaFleur - MSFT).

Now I really work on the call of the API that would permit to download the files I want. This is how I proceeded:

1- As I've seen in the Microsoft Graph Documentation, the normal syntax would be the following:

curl -w %{time_total} https://graph.microsoft.com/v1.0/me/drive/items/01M...WU/content -H "Authorization: Bearer $access_token"

2- However, this gives me a 302 request, which I can't handle in bash. So I looked for another solution and I found this Microsoft article explaining that:

"To download files from OneDrive in a JavaScript app you cannot use the /content API, since this responds with a 302 redirect. A 302 redirect is explicitly prohibited when a CORS preflight is required, such as when providing the Authorization header.

Instead, your app needs to select the @microsoft.graph.downloadUrl property, which returns the same URL that /content would have redirected to. This URL can then be requested directly using XMLHttpRequest. Because these URLs are pre-authenticated they can be retrieved without a CORS preflight request."

It talks about Javascript but I think it can be applied to my case.

3- So I tried this method and I wrote:

curl "https://graph.microsoft.com/v1.0/me/drive/items/01MB...WU?select=id,@microsoft.graph.downloadUrl" -H "Authorization: Bearer $access_token"

It gave me the URL that normally would permit me to finally download the file, but when I execute it, I get the following response:

Code:

curl "https://graph.microsoft.com/v1.0/$metadata#users('e967dd4d-680e-4a06-9bf7-468875e1a04c')/drive/items/$entity" -H "Authorization: Bearer $access_token" (it is exactly what I got with the previous request)

Response:

enter image description here

Any help? Why is it a bad request since I've put exactly what I got from the graph.microsoft.com request?

Community
  • 1
  • 1
Héloïse Chauvel
  • 502
  • 3
  • 6
  • 21

1 Answers1

2

https://graph.microsoft.com/v1.0/$metadata#users('e967dd4d-680e-4a06-9bf7-468875e1a04c')/drive/items/$entity is the @odata.context annotation, which is not what you're after. You need to pull the URL out of the @microsoft.graph.downloadUrl annotation and use that to grab the file contents. The URL you're after should mention download.aspx in it.

Brad
  • 4,089
  • 2
  • 16
  • 26
  • Thank you for your answer. Just one more precision: when I execute `curl "https://graph.microsoft.com/v1.0/me/drive/items/01MB...WU?select=id,@microsoft.graph.downloadUrl" -H "Authorization: Bearer $access_token"`, I have only the `@odata.context`, the `@odata.etag`, the id and `1\""` (I don't know what this last annotation stands for). I don't have the `@content.downloadUrl`. So, I directly put the URL without select parameters and I got it but why the select parameter doesn't retrieve the right property? – Héloïse Chauvel May 10 '17 at 08:09
  • A couple of things. 1) I should have said `@microsoft.graph.downloadUrl` as `@content.downloadUrl` is only relevant when calling the OneDrive API directly. 2) You've found a bug! We're not handling `@microsoft.graph.downloadUrl` properly in the select statement so I'll get that fixed. – Brad May 11 '17 at 03:41
  • Got it. Keep us up to date when fixed. – Héloïse Chauvel May 11 '17 at 08:39
  • Here's the issue we'll use to track it https://github.com/OneDrive/onedrive-api-docs/issues/606. – Brad May 11 '17 at 14:52
  • Actually, as a work around you can `select=@content.downloadUrl` and it'll return the `@microsoft.graph.downloadUrl` – Brad May 11 '17 at 15:25
  • Thank you Brad. Are these downloadUrls permanent? I mean can I call the curl command only once, store the result URL in a file and reuse it without calling Microsoft one more time? Because for the moment I call this command for each file I want to download at each execution of my script and it slows it down. – Héloïse Chauvel May 12 '17 at 09:17
  • The URLs will expire within a small period of time, so they're really intended to be used instantly and not cached. The expectation is that if you need to cache the URL, you should instead cache the URL to the resource and fetch a new download URL "just in time". – Brad May 12 '17 at 17:31
  • FYI, you can now `select=@microsoft.graph.downloadUrl` in graph and it will work. Yay! – Brad Jul 19 '17 at 16:13