简体   繁体   English

使用MS Graph SDK从共享的OneDrive文件夹下载并上传DriveItem

[英]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: 因此, 要从文件夹下载内容,解决方案将是:

  • enumerate items under folder: GET /drives/{drive-id}/items/{folderItem-id}/children 枚举文件夹下的项目: GET /drives/{drive-id}/items/{folderItem-id}/children
  • per every item explicitly download its content if 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 copymove操作。 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.

相关问题 如何使用C#从OneDrive中的共享文件夹下载文件? - How to download a file from shared folder in onedrive using c#? Microsoft Graph .Net API:共享的OneDrive文件夹 - Microsoft Graph .Net API: Shared OneDrive folder UWP - 使用 MS Graph 团队的示例代码时,OneDrive 文件下载错误:“访问路径 '...' 被拒绝” - UWP - OneDrive file download error: “Access to the path '…' is denied” when using sample code from MS Graph team 如何使用OneDrive API将文件上传到OneDrive上的共享文件夹中? - How can I upload files into a shared folder on OneDrive using OneDrive API? 如何使用OneDrive SDK将OneDrive上的文件夹/文件上传到Windows 10 UWP - How to upload a folder/file on onedrive using the onedrive sdk for windows 10 UWP 从OneDrive C#SDK访问共享的单个文件 - Accessing Shared Single Files from OneDrive C# SDK ms-graph API 与 C#; 如何修复此驱动项错误 - ms-graph API with C#; how to fix this driveitem error MS Graph API:使用 PostAsync 复制 driveItem 不会返回结果 - MS Graph API: Copying a driveItem using PostAsync does not return a result Microsoft Graph:将文件从URL [C#]上传到onedrive - Microsoft Graph: upload files to onedrive from URL [C#] OneDrive上传/下载到指定目录 - OneDrive Upload/Download to Specified Directory
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM