How to download a file using a Sharepoint REST API

Jose Larios 0 Reputation points
2024-07-16T02:20:02.2133333+00:00

I am trying to download files from Sharepoint using the Sharepoint REST API from a web app; my code needs to eventually work with Sharepoint Subscription Edition (and maybe even Sharepoint 2019), but for dev purposes I have created a test Sharepoint Online account and uploaded files there. I seem to have been able to authenticate ok using msal-browser, but I can't seem to get any information about files or folders in the Sharepoint document library; my GetFolderByServerRelativeUrl('Shared Documents') calls return 403 Forbidden. Interestingly, a call to https://xxxx.sharepoint.com/_api/web/lists does seem to work ok, though I'm not sure how I might get from the lists to the proper path/url to the document(s) I'm interested in. I suspect I might not be using the right scope(s) for the Sharepoint REST API that I'm trying to use. I don't believe I can use the Graph API because of my need to be backwards compatible with Subscription Edition and maybe even 2019.

Here are the API Permissions I have on the app registration (I'm not sure which of these, if any, might actually be needed, given that the code I have that seems to be closest to working doesn't actually requests any of these in the 'scopes'):

  • Microsoft Graph
    • Files.Read.All
    • User.Read
  • SharePoint
    • AllSites.Read
    • MyFiles.Read

Here's how I get the access token:

  async _getAccessToken(): Promise<string> {

  	const msalConfig = {
    	auth: {
        	clientId: "<myClientId>",
        	authority: "https://login.microsoftonline.com/<myAuthority>",
        	redirectUri: "https://myMachine",
   	 	},
    	cache: {
        	cacheLocation: "sessionStorage",
        	storeAuthStateInCookie: false
    	}
  	};

    const msalInstance = new PublicClientApplication(msalConfig);
    await msalInstance.initialize();

    const loginRequest = {
      scopes: ["https://xxxx.sharepoint.com/.default"
               /* "Files.Read.All", "MyFiles.Read"*/
              ],
      skipCache: false, // This skips the cache if set to true
    };
    
    try {
      const authResult = await msalInstance.loginPopup(loginRequest);
      console.log("authResult: ", authResult);
      if (authResult == null) {
        console.error("Did not get an access token.")
        this._selectAccount(msalInstance);
        return "";
        // const ssoSilentResponse = await msalInstance.ssoSilent(silentRequest);
        // return ssoSilentResponse.accessToken;
      } else {
        console.log(`Returning access token ${authResult.accessToken}`);
        return authResult.accessToken;
      }
    } catch (error) {
      console.log(error);
      // if (error instanceof InteractionRequiredAuthError) {
      //     signIn();
      // }
      throw error;
    }
  }

This then works with the returned access token:

            let response = await esriRequest(`https://xxxx.sharepoint.com/_api/web/lists`, {
              method: "GET",
              headers: {
                Authorization: `Bearer ${accesssToken}`,
                Accept: "application/json;odata=verbose "
              }
            });


This results in a 403 Forbidden error:

            let response = await esriRequest(`https://xxxx.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('Shared Documents')`, {
              method: "GET",
              headers: {
                Authorization: `Bearer ${accesssToken}`,
                Accept: "application/octet-stream;odata=verbose"
              }
            });

This results in a 400 Bad Request:

            let response = await esriRequest(`https://xxxx.sharepoint.com/_api/web/GetFileByServerRelativeUrl('Shared Documents/myFile.pdf')/$value`, {
              method: "GET",
              headers: {
                Authorization: `Bearer ${accesssToken}`,
                Accept: "application/octet-stream;odata=verbose"
              }
            });

I do realize that I'm not referencing a Sharepoint site in the form of /sites/xyz/ as I often see. I think this should theoretically be OK as I'm using my admin account when I'm doing this, so I think this should all still theoretically work...however, I did create another test Sharepoint site "xyz" under this tenant to see if there would be any difference. In that case, I am setting this as the scope: https://xxxx.sharepoint.com/sites/xyz/.default when logging in, and I get this error: invalid_resource: AADSTS500011: The resource principal named https://xxxx.sharepoint.com/sites/xyz was not found in the tenant named MSFT. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.

I would be incredibly grateful for any pointers!!

SharePoint
SharePoint
A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.
10,275 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Yanli Jiang - MSFT 24,121 Reputation points Microsoft Vendor
    2024-07-16T09:01:03.6266667+00:00

    Hi @Jose Larios ,

    According to the information you provided, you need to check the following:

    1. Permission issue. Your requirement is to download files, and only read permission is not enough. You also need Edit permission. The AADSTS500011 error may also be caused by permission issues. So, please add enough permissions.
    2. Access token issue You can use this tool https://jwt.io/to check whether your access token has errors.

    While Microsoft supports and encourages open-source software development, it does not provide technical support for the softwares from third parties, nor does it guarantee that the software will work as described.

    1. Code issue. You can try to use the official method to download files. Or you can try the Graph api, which is easier to use.

    References:

    https://learn.microsoft.com/en-us/answers/questions/1080601/how-to-download-file-fromsharepoint-using-api

    https://learn.microsoft.com/en-us/answers/questions/601256/downloading-file-from-sharepoint-site-folder-using

    Have a nice day!


    If the answer is helpful, please click "Accept as Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.