Search code examples
angulartypescriptsafaricorssharepoint-rest-api

How can I download a file from OneDrive into Angular application using Typescript?


I have an Angular application that is using OneDrive/Sharepoint to store files it has created. Authentication is working correctly and I can save my files successfully. I am having a problem with downloading the file that I created and stored using the Angular HttpClient.

My code looks like this:

export class MicrosoftService {

   private graphUri = 'https://graph.microsoft.com/v1.0';

   constructor(private http: HttpClient) {}

   public loadFile(id: string, next: (saved: string) => void): void {
  
        this.http.get(this.graphUri + '/me/drive/items/' + id + '/content', { headers: this.getOAuthHeader() })
             .subscribe((response: any) => {
                console.log(response.toString());
                next(response.toString());
            });
    }

    getOAuthHeader(): HttpHeaders {
       // a bunch of stuff that generates the OAuth headers, definitely works
    }

}

Obviously I'll do something else with the response when I can receive it.

The problem is that when the GET request is triggered it correctly makes a request to graph, which then returns a 302 redirect to https://foozlecorporation-my.sharepoint.com/drive/path/_layouts/15/download.aspx?UniqueId=a-bunch-of-url-params - this is also correct and I can download the content from a REST client, but in the browser (currently using Safari) the redirect raises a Browser cannot load [...url...] due to access control checks error.

I have Access-Control-Allow-Origin: * in my application headers, which is presumably why I can use Graph in the first place, but the Sharepoint response does not include Access-Control-Allow-Origin. What more do I need to do?


Solution

  • Problem

    You write that endpoint https://foozlecorporation-my.sharepoint.com/drive/path/_layouts/15/download.aspx?UniqueId=a-bunch-of-url-params doesn't responds with any Access-Control-Allow-Origin header.

    When you send, from origin A, a CORS request to some endpoint on origin B (https://graph.microsoft.com) and the response allows origin A but results in a cross-origin redirect to some endpoint on origin C (https://foozlecorporation-my.sharepoint.com), the browser carries out a new CORS access-control check for origin A on origin C. If origin C isn't configured for CORS or doesn't allow origin A, your overall CORS request will fail.

    Possible solution

    One solution consists in making the call to https://graph.microsoft.com from your backend rather than from your frontend; that way, because CORS doesn't apply to non-browser user agents, you'd sidestep the problem.