我当前正在尝试执行一些任务,这些任务涉及从共享的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
}
}
我的问题始于“将子项下载到路径”部分。我要在那里下载所有内容,而不是将其下载到临时文件的文件夹。问题是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
方法(就像在创建文件夹中一样),因为我不知道如何从DriveItem
创建Stream
。
如果有人可以指出正确的方向,我将非常感激!谢谢!
答案 0 :(得分:3)
请求:
graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync()
对应于Download the contents of a DriveItem端点,并且仅在childItem.ParentReference.Id
引用File
resource时有效,在另一种情况下,它会失败并出现预期的异常:
Microsoft.Graph.ServiceException:代码:itemNotFound消息:您 无法获取文件夹内容
因此,要从文件夹下载内容,解决方案是:
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);
}
}
我认为您实际上所要做的是DriveItem
copy
或move
操作,而不是下载/上传文件内容。假设有一些文件需要从一个(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)
{
var parentReference = new ItemReference
{
DriveId = targetDriveId,
Id = targetItemFolderId
};
await graphClient.Drives[sourceDriveId].Items[item.Id]
.Copy(item.Name, parentReference)
.Request()
.PostAsync();
}
}
}