[英]Download and upload DriveItem from shared OneDrive Folder with MS Graph SDK
I'm currently trying to implement several tasks that involve listing, uploading and downloading files from a shared OneDrive folder. 我目前正在尝试实现几个涉及列出,上传和下载共享OneDrive文件夹中的文件的任务。 This folder is accesible via the logged in users OneDrive (visible in his root folder).
可以通过登录用户OneDrive访问此文件夹(在其根文件夹中可见)。 The listing part works pretty well so far, using this code:
到目前为止,列表部分运行良好,使用此代码:
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();
}
So obviously I need to retrieve the shared folders information from the OneDrive that shared it with the other OneDrive. 显然,我需要从与其他OneDrive共享它的OneDrive中检索共享文件夹信息。 Next part for me is to list the contents of this shared folder, which also works pretty well like this:
对我来说,下一部分是列出这个共享文件夹的内容,它也可以很好地工作:
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
}
}
My problem starts with the "Download child item to path" part. 我的问题始于“将子项目下载到路径”部分。 There I want to download everything, that is not a folder to a temporary file.
在那里,我想下载所有内容,这不是临时文件的文件夹。 The problem is that OneDrive always answers my request with an error message, that the file was not found.
问题是OneDrive总是回复我的请求,并显示错误消息,表明找不到该文件。 What I tried so far is:
到目前为止我尝试的是:
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);
}
In another variant I tried to use the ID of the childItem ParentReference (but I think this will only lead me to the remote OneDrives ID of sharedFolder): 在另一个变种中,我尝试使用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);
}
After Downloading the files I want to edit them and reupload them to a different path in the shared folder. 下载我想编辑的文件后,将它们重新上载到共享文件夹中的不同路径。 That path is created by me (which allready works) like this:
那个路径是由我创建的(已经可以工作),如下所示:
DriveItem folderToCreate = new DriveItem { Name = "folderName", Folder = new Folder() };
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Children.Request().AddAsync(folderToCreate);
The upload then fails. 然后上传失败。 I've tried it like this:
我试过这样的:
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);
}
And also like this (which works if it is not a shared folder and I therefore use Drive
instead of Drives
): 并且像这样(如果它不是共享文件夹,它可以工作,因此我使用
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);
}
I couldn't get the AddAsync
method (like in the folder creation) to work because I don't know how to create a DriveItem
from a Stream
. 我无法使
AddAsync
方法(如在文件夹创建中)工作,因为我不知道如何从Stream
创建DriveItem
。
If somebody could point me in the right direction I would highly appreciate that! 如果有人能指出我正确的方向,我将非常感谢! Thank you!
谢谢!
The request: 请求:
graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync()
corresponds to Download the contents of a DriveItem endpoint and is only valid if childItem.ParentReference.Id
refers to a File
resource , in another cases it fails with expected exception: 对应于下载DriveItem端点的内容, 仅在
childItem.ParentReference.Id
引用File
资源时有效 ,在另一种情况下,它会因预期的异常而失败:
Microsoft.Graph.ServiceException: Code: itemNotFound Message: You cannot get content for a folder
Microsoft.Graph.ServiceException:代码:itemNotFound消息:您无法获取文件夹的内容
So, to download content from a folder the solution would be to: 因此, 要从文件夹下载内容,解决方案将是:
GET /drives/{drive-id}/items/{folderItem-id}/children
GET /drives/{drive-id}/items/{folderItem-id}/children
driveItem
corresponds to a File
facet: GET /drives/{drive-id}/items/{fileItem-id}/content
driveItem
对应于File
facet,则每个项目显式下载其内容: GET /drives/{drive-id}/items/{fileItem-id}/content
Example 例
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);
}
}
Example 2 例2
The example demonstrates how to download file from a source folder and upload it into a target folder: 该示例演示如何从源文件夹下载文件并将其上载到目标文件夹:
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);
}
}
Instead of downloading/uploading file content, i think what you are actually after is DriveItem
copy
or move
operations. 而不是下载/上传文件内容,我认为你实际上是在
DriveItem
copy
或move
操作。 Lets say there are files that needs to be copied from one ( source
) folder into another ( target
), then the following example demonstrates how to accomplish it: 比方说有一些需要从一个( 复制的文件
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();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.