I have several Office 365 SharePoint sites. I would like my NodeJS based daemon that is registered as an Azure App Registration to write to several different folders within these SharePoint sites. I am struggling to get the correct syntax of the request url correct to create a resumable upload session. This is made worse by fairly unclear and non working examples provided by Microsoft. An important detail here is that the application is doing this without user delegation, meaning no user is using the application to cause these files but rather it is and should be the entity who owns the file uploads. Many examples show how to do this with user delegation. Some of the files being uploaded include binary or text content.
I have read quite a bit of the ms docs and referred to many questions. I even watched many videos on YouTube and started digging through source code with the microsoft-graph-client
incase there were insights to be had there. I don't think I can review graph server code or if that would be helpful. Below are just a few that I still I have open due to being closely related.
Here is my latest attempt which I feel should be getting pretty close:
const msal = require('@azure/msal-node');
const graph = require( '@microsoft/microsoft-graph-client' );
// all that client initialization and authentication work so I omited it for this example
const fileName = 'fileName.txt';
const filePath = 'path/to/file/' + fileName;
const stats = fs.statSync( filePath );
const totalSize = stats.size;
const readStream = fs.createReadStream( filePath );
const fileObject = new graph.StreamUpload( readStream, fileName, totalSize );
const site_id = '' // refers to the identifier for the SharePoint site, something like domain,guid,guid
const drive_id = '' // refers to the site specific drive that would sync to the Corp OneDrive folder
const item_id = '' // refers to the ID for a target folder
let folder1, folder2, folder3 // refer to possible folders. I assumed I could just specify the ID of the last one to upload into it
requestUrl = `https://graph.microsoft.com/v1.0/sites/${ site_id }/drives/${ drive_id }/items/${ item_id }/${ fileName }:/createuploadsession`
// OR
requestUrl = `https://graph.microsoft.com/v1.0/drives/${ drive_id }/items/${ item_id }/${ fileName }:/createuploadsession`
// OR
requestUrl = `https://graph.microsoft.com/v1.0/drives/${ drive_id }/root:/${ folder1 }/${ fileName }:/createuploadsession`
// OR
requestUrl = `https://graph.microsoft.com/v1.0/drives/${ drive_id }/root:/${ folder1 }:/${ fileName }:/createuploadsession`
// OR
requestUrl = `https://graph.microsoft.com/v1.0/drives/${ drive_id }/root:/${ folder1 }/${ folder2 }/${ fileName }:/createuploadsession`
// OR
requestUrl = `https://graph.microsoft.com/v1.0/drives/${ drive_id }/root:/${ folder1 }/${ folder2 }/${ folder3 }/${ fileName }:/createuploadsession`
const uploadSession = await new graph.LargeFileUploadTask.createUploadSession( client, requestUrl, payload );
// here usually results in (node:0) UnhandledPromiseRejectionWarning: Error: Invalid request
const uploadTask = await graph.LargeFileUploadTask( client, fileObject, uploadSession, options );
const uploadResult = await uploadTask.upload();
console.log( uploadResult?.responseBody || uploadResult )
Project 1:
Documents
library where we sync files using OneDrive for BusinessProject 1 - Documents
through OneDriveProject 2: etc
Team 1:
Team 2: etc
Here is how we see it from OneDrive:
And in Teams:
I had to add a colon after the folder_id for the 2nd requestUrl format.
Also the await graph.LargeFileUploadTask
had to become new graph.LargeFileUploadTask
const msal = require('@azure/msal-node');
const graph = require( '@microsoft/microsoft-graph-client' );
// all that client initialization and authentication work so I omited it for this example
const fileName = 'fileName.txt';
const filePath = 'path/to/file/' + fileName;
const stats = fs.statSync( filePath );
const totalSize = stats.size;
const readStream = fs.createReadStream( filePath );
const fileObject = new graph.StreamUpload( readStream, fileName, totalSize );
const site_id = '' // refers to the identifier for the SharePoint site, something like domain,guid,guid
const drive_id = '' // refers to the site specific drive that would sync to the Corp OneDrive folder
const folder_id = '' // refers to the ID for a target folder
requestUrl = `https://graph.microsoft.com/v1.0/drives/${ drive_id }/items/${ folder_id }:/${ fileName }:/createuploadsession`
const uploadSession = await new graph.LargeFileUploadTask.createUploadSession( client, requestUrl, payload );
// here usually results in (node:0) UnhandledPromiseRejectionWarning: Error: Invalid request
const uploadTask = new graph.LargeFileUploadTask( client, fileObject, uploadSession, options );
const uploadResult = await uploadTask.upload();
console.log( uploadResult?.responseBody || uploadResult )