使用 Microsoft Graph 创建上传会话到 Office 365 上的 Sharepoint 站点文件夹

create upload session to sharepoint site folder on Office 365 using microsoft graph

TLDR;

我有几个 Office 365 SharePoint 网站。我希望注册为 Azure 应用程序注册的基于 NodeJS 的守护程序写入这些 SharePoint 站点中的几个不同文件夹。我正在努力使请求 url 的正确语法正确以创建可恢复的上传会话。 Microsoft 提供的相当不明确且无效的示例使情况变得更糟。这里的一个重要细节是应用程序在没有用户授权的情况下执行此操作,这意味着没有用户使用该应用程序来生成这些文件,而是它是并且应该是拥有文件上传的实体。许多示例展示了如何通过用户委派来做到这一点。正在上传的一些文件包括二进制或文本内容。

我已经阅读了相当多的 ms 文档并提到了很多问题。我什至在 YouTube 上看了很多视频,并开始使用 microsoft-graph-client 挖掘源代码,以防那里有见解。我不认为我可以查看图形服务器代码或者这是否有帮助。由于关系密切,以下是我仍然开放的一些。

这是我最近的一次尝试,我觉得应该很接近了:

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 )

应用程序堆栈:

站点和文件夹快速概览:

项目 1:

  1. 我们有很多来来去去的项目,所以我们将这些项目的文件和参与这些项目的人员分开。我不会改变我们构建项目的方式,因为这是一个长期存在的问题,背后有很多原因。对该主题的 /dev/null 的评论。
  2. 包含一个 Documents 库,我们在其中使用 OneDrive for Business 同步文件
  3. 为此创建了一个 Teams 站点,我们在其中创建了创建文件夹的通道,我们可以在 Project 1 - Documents 中通过 OneDrive
  4. 访问这些文件夹
  5. 想将文件上传到此处文件夹结构的任何级别。

项目 2:等等

第 1 队:

  1. 与项目相同,但在这里我们进行特定于团队的互动。
  2. 我们有很多团队,相当于公司内部的部门和子部门。
  3. 想将文件上传到此处文件夹结构的任何级别。文件夹的 ID 很可能是长期的,但如果有人删除它们,我们可能应该根据路径找到文件夹的 ID。

第 2 队:等等

这是我们从 OneDrive 中看到的:

在 Teams 中:

我不得不在 folder_id 之后为第二个 requestUrl 格式添加一个冒号。 await graph.LargeFileUploadTask 也必须变成 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 )