使用 MS Graph SDK 从共享的 OneDrive 文件夹下载和上传 DriveItem
Download and upload DriveItem from shared OneDrive Folder with MS Graph SDK
我目前正在尝试执行多项任务,包括从共享的 OneDrive 文件夹中列出、上传和下载文件。可通过登录用户 OneDrive 访问此文件夹(在其根文件夹中可见)。到目前为止,列表部分运行良好,使用此代码:
string remoteDriveId = string.Empty;
private GraphServiceClient graphClient { get; set; }
// Get the root of the owners OneDrive
DriveItem ownerRoot = await this.graphClient.Drive.Root.Request().Expand("thumbnails,children($expand=thumbnails)").GetAsync();
// Select the shared folders general information
DriveItem sharedFolder = ownerRoot.Children.Where(c => c.Name == "sharedFolder").FirstOrDefault();
// Check if it is a remote folder
if(sharedFolder.Remote != null)
{
remoteDriveId = item.RemoteItem.ParentReference.DriveId;
// Get complete Information of the shared folder
sharedFolder = await graphClient.Drives[remoteDriveId].Items[sharedFolder.RemoteItem.Id].Request().Expand("thumbnails,children").GetAsync();
}
很明显,我需要从与其他 OneDrive 共享的 OneDrive 中检索共享文件夹信息。
我的下一部分是列出这个共享文件夹的内容,它也像这样工作得很好:
foreach (DriveItem child in sharedFolder.Children)
{
DriveItem childItem = await graphClient.Drives[remoteDriveId].Items[child.Id].Request().Expand("thumbnails,children").GetAsync();
if(childItem.Folder == null)
{
string path = Path.GetTempPath() + Guid.NewGuid();
// Download child item to path
}
}
我的问题从 "Download child item to path" 部分开始。在那里我想下载所有东西,那不是临时文件的文件夹。问题是 OneDrive 总是用一条错误消息来回答我的请求,即找不到文件。到目前为止我尝试的是:
using (var stream = await graphClient.Drives[remoteDriveId].Items[childItem.Id].Content.Request().GetAsync())
using (var outputStream = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
await stream.CopyToAsync(outputStream);
}
在另一个变体中,我尝试使用 childItem ParentReference 的 ID(但我认为这只会将我带到 sharedFolder 的远程 OneDrives ID):
using (var stream = await graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync())
using (var outputStream = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
await stream.CopyToAsync(outputStream);
}
下载文件后,我想编辑它们并将它们重新上传到共享文件夹中的不同路径。该路径是由我创建的(已经可以使用),如下所示:
DriveItem folderToCreate = new DriveItem { Name = "folderName", Folder = new Folder() };
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Children.Request().AddAsync(folderToCreate);
上传失败。我试过这样:
using (var stream = new System.IO.FileStream(@"C:\temp\testfile.txt", System.IO.FileMode.Open))
{
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Content.Request().PutAsync<DriveItem>(stream);
}
也喜欢这样(如果它不是共享文件夹,它会起作用,因此我使用 Drive
而不是 Drives
):
using (var stream = new System.IO.FileStream(@"C:\temp\testfile.txt", System.IO.FileMode.Open))
{
string folderPath = sharedFolder.ParentReference == null ? "" : sharedFolder.ParentReference.Path.Remove(0, 12) + "/" + Uri.EscapeUriString(sharedFolder.Name);
var uploadPath = folderPath + "/" + uploadFileName;
await graphClient.Drives[remoteDriveId].Root.ItemWithPath(uploadPath).Content.Request().PutAsync<DriveItem>(stream);
}
我无法使用 AddAsync
方法(就像在文件夹创建中一样),因为我不知道如何从 Stream
创建 DriveItem
。
如果有人能指出正确的方向,我将不胜感激!谢谢!
请求:
graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync()
对应于Download the contents of a DriveItem endpoint and is only valid if childItem.ParentReference.Id
refers to a File
resource,在另一种情况下它失败并出现预期的异常:
Microsoft.Graph.ServiceException: Code: itemNotFound Message: You
cannot get content for a folder
因此,要从文件夹下载内容,解决方案是:
- 枚举文件夹下的项目:
GET /drives/{drive-id}/items/{folderItem-id}/children
- 如果
driveItem
对应于 File
方面,则每个项目明确下载其内容:GET /drives/{drive-id}/items/{fileItem-id}/content
例子
var sharedItem = await graphClient.Drives[driveId].Items[folderItemId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sharedItem.Children)
{
if (item.File != null)
{
var fileContent = await graphClient.Drives[item.ParentReference.DriveId].Items[item.Id].Content.Request()
.GetAsync();
using (var fileStream = new FileStream(item.Name, FileMode.Create, System.IO.FileAccess.Write))
fileContent.CopyTo(fileStream);
}
}
示例 2
该示例演示了如何从 source 文件夹下载文件并将其上传到 target 文件夹:
var sourceDriveId = "--source drive id goes here--";
var sourceItemFolderId = "--source folder id goes here--";
var targetDriveId = "--target drive id goes here--";
var targetItemFolderId = "--target folder id goes here--";
var sourceFolder = await graphClient.Drives[sourceDriveId].Items[sourceItemFolderId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sourceFolder.Children)
{
if (item.File != null)
{
//1. download a file as a stream
var fileContent = await graphClient.Drives[item.ParentReference.DriveId].Items[item.Id].Content.Request()
.GetAsync();
//save it into file
//using (var fileStream = new FileStream(item.Name, FileMode.Create, System.IO.FileAccess.Write))
// fileContent.CopyTo(fileStream);
//2.Upload file into target folder
await graphClient.Drives[targetDriveId]
.Items[targetItemFolderId]
.ItemWithPath(item.Name)
.Content
.Request()
.PutAsync<DriveItem>(fileContent);
}
}
而不是 downloading/uploading 文件内容,我认为你真正想要的是 DriveItem
copy
or move
操作。假设有一些文件需要从一个 (source
) 文件夹 copied 到另一个 (target
) 文件夹,那么下面的例子演示了如何完成它:
var sourceDriveId = "--source drive id goes here--";
var sourceItemFolderId = "--source folder id goes here--";
var targetDriveId = "--target drive id goes here--";
var targetItemFolderId = "--target folder id goes here--";
var sourceFolder = await graphClient.Drives[sourceDriveId].Items[sourceItemFolderId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sourceFolder.Children)
{
if (item.File != null)
{
var parentReference = new ItemReference
{
DriveId = targetDriveId,
Id = targetItemFolderId
};
await graphClient.Drives[sourceDriveId].Items[item.Id]
.Copy(item.Name, parentReference)
.Request()
.PostAsync();
}
}
}
我目前正在尝试执行多项任务,包括从共享的 OneDrive 文件夹中列出、上传和下载文件。可通过登录用户 OneDrive 访问此文件夹(在其根文件夹中可见)。到目前为止,列表部分运行良好,使用此代码:
string remoteDriveId = string.Empty;
private GraphServiceClient graphClient { get; set; }
// Get the root of the owners OneDrive
DriveItem ownerRoot = await this.graphClient.Drive.Root.Request().Expand("thumbnails,children($expand=thumbnails)").GetAsync();
// Select the shared folders general information
DriveItem sharedFolder = ownerRoot.Children.Where(c => c.Name == "sharedFolder").FirstOrDefault();
// Check if it is a remote folder
if(sharedFolder.Remote != null)
{
remoteDriveId = item.RemoteItem.ParentReference.DriveId;
// Get complete Information of the shared folder
sharedFolder = await graphClient.Drives[remoteDriveId].Items[sharedFolder.RemoteItem.Id].Request().Expand("thumbnails,children").GetAsync();
}
很明显,我需要从与其他 OneDrive 共享的 OneDrive 中检索共享文件夹信息。 我的下一部分是列出这个共享文件夹的内容,它也像这样工作得很好:
foreach (DriveItem child in sharedFolder.Children)
{
DriveItem childItem = await graphClient.Drives[remoteDriveId].Items[child.Id].Request().Expand("thumbnails,children").GetAsync();
if(childItem.Folder == null)
{
string path = Path.GetTempPath() + Guid.NewGuid();
// Download child item to path
}
}
我的问题从 "Download child item to path" 部分开始。在那里我想下载所有东西,那不是临时文件的文件夹。问题是 OneDrive 总是用一条错误消息来回答我的请求,即找不到文件。到目前为止我尝试的是:
using (var stream = await graphClient.Drives[remoteDriveId].Items[childItem.Id].Content.Request().GetAsync())
using (var outputStream = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
await stream.CopyToAsync(outputStream);
}
在另一个变体中,我尝试使用 childItem ParentReference 的 ID(但我认为这只会将我带到 sharedFolder 的远程 OneDrives ID):
using (var stream = await graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync())
using (var outputStream = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
await stream.CopyToAsync(outputStream);
}
下载文件后,我想编辑它们并将它们重新上传到共享文件夹中的不同路径。该路径是由我创建的(已经可以使用),如下所示:
DriveItem folderToCreate = new DriveItem { Name = "folderName", Folder = new Folder() };
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Children.Request().AddAsync(folderToCreate);
上传失败。我试过这样:
using (var stream = new System.IO.FileStream(@"C:\temp\testfile.txt", System.IO.FileMode.Open))
{
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Content.Request().PutAsync<DriveItem>(stream);
}
也喜欢这样(如果它不是共享文件夹,它会起作用,因此我使用 Drive
而不是 Drives
):
using (var stream = new System.IO.FileStream(@"C:\temp\testfile.txt", System.IO.FileMode.Open))
{
string folderPath = sharedFolder.ParentReference == null ? "" : sharedFolder.ParentReference.Path.Remove(0, 12) + "/" + Uri.EscapeUriString(sharedFolder.Name);
var uploadPath = folderPath + "/" + uploadFileName;
await graphClient.Drives[remoteDriveId].Root.ItemWithPath(uploadPath).Content.Request().PutAsync<DriveItem>(stream);
}
我无法使用 AddAsync
方法(就像在文件夹创建中一样),因为我不知道如何从 Stream
创建 DriveItem
。
如果有人能指出正确的方向,我将不胜感激!谢谢!
请求:
graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync()
对应于Download the contents of a DriveItem endpoint and is only valid if childItem.ParentReference.Id
refers to a File
resource,在另一种情况下它失败并出现预期的异常:
Microsoft.Graph.ServiceException: Code: itemNotFound Message: You cannot get content for a folder
因此,要从文件夹下载内容,解决方案是:
- 枚举文件夹下的项目:
GET /drives/{drive-id}/items/{folderItem-id}/children
- 如果
driveItem
对应于File
方面,则每个项目明确下载其内容:GET /drives/{drive-id}/items/{fileItem-id}/content
例子
var sharedItem = await graphClient.Drives[driveId].Items[folderItemId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sharedItem.Children)
{
if (item.File != null)
{
var fileContent = await graphClient.Drives[item.ParentReference.DriveId].Items[item.Id].Content.Request()
.GetAsync();
using (var fileStream = new FileStream(item.Name, FileMode.Create, System.IO.FileAccess.Write))
fileContent.CopyTo(fileStream);
}
}
示例 2
该示例演示了如何从 source 文件夹下载文件并将其上传到 target 文件夹:
var sourceDriveId = "--source drive id goes here--";
var sourceItemFolderId = "--source folder id goes here--";
var targetDriveId = "--target drive id goes here--";
var targetItemFolderId = "--target folder id goes here--";
var sourceFolder = await graphClient.Drives[sourceDriveId].Items[sourceItemFolderId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sourceFolder.Children)
{
if (item.File != null)
{
//1. download a file as a stream
var fileContent = await graphClient.Drives[item.ParentReference.DriveId].Items[item.Id].Content.Request()
.GetAsync();
//save it into file
//using (var fileStream = new FileStream(item.Name, FileMode.Create, System.IO.FileAccess.Write))
// fileContent.CopyTo(fileStream);
//2.Upload file into target folder
await graphClient.Drives[targetDriveId]
.Items[targetItemFolderId]
.ItemWithPath(item.Name)
.Content
.Request()
.PutAsync<DriveItem>(fileContent);
}
}
而不是 downloading/uploading 文件内容,我认为你真正想要的是 DriveItem
copy
or move
操作。假设有一些文件需要从一个 (source
) 文件夹 copied 到另一个 (target
) 文件夹,那么下面的例子演示了如何完成它:
var sourceDriveId = "--source drive id goes here--";
var sourceItemFolderId = "--source folder id goes here--";
var targetDriveId = "--target drive id goes here--";
var targetItemFolderId = "--target folder id goes here--";
var sourceFolder = await graphClient.Drives[sourceDriveId].Items[sourceItemFolderId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sourceFolder.Children)
{
if (item.File != null)
{
var parentReference = new ItemReference
{
DriveId = targetDriveId,
Id = targetItemFolderId
};
await graphClient.Drives[sourceDriveId].Items[item.Id]
.Copy(item.Name, parentReference)
.Request()
.PostAsync();
}
}
}