1

I was not able to find any example on how to upload a file to a SharePoint library sub-folder using the MS Graph SDK.

These posts show how to do that using the REST API, but not the C# SDK.

upload files in a folder in Sharepoint/OneDrive library using graph api

How to perform a resumable Upload to a SharePoint Site (Not Root) Subfolder using MS Graph API

Ciro di Marzo
  • 391
  • 2
  • 15

1 Answers1

0

This is how I did it in the end:

try
{
    using var stream = new MemoryStream(contentBytes);

    // Retrieve the folder item.
    var items = await this._graphClient.Sites["siteId"].Lists["listId"].Items
        .Request()
        .GetAsync();

    // I happened to know the folder name in advance, so that is what I used to retrieve the folder item from Items collection.
    // I could not find how to query the Graph to get just the folder instead of all the items. Hopefully I will find it and update the code.
    var folderItem = items.FirstOrDefault(i => i.WebUrl.Contains($"{path}") && i.ContentType.Name == "Folder");

    // you must create a DriveItem, not a ListItem object. It is important to set the the File property.
    var listItem = new DriveItem
    {
        Name = fileName,
        File = new Microsoft.Graph.File(),
        AdditionalData = new Dictionary<string, object>()
                {
                    { "@microsoft.graph.conflictBehavior", "replace" }
                },

    };

    listItem = await this._graphClient.Sites["siteId"].Lists["listId"].Items[folderItem.Id].DriveItem.Children
        .Request()
        .AddAsync(listItem);

    // I needed the drive Id here. it is in the Drives properties of the site. It corresponds to the drive associated to the library.
    var uploadSession = await this._graphClient.Sites["siteId"].Drives["driveId"]
        .Items[listItem.Id]
        .CreateUploadSession()
        .Request()
        .PostAsync();

    var largeFileUploadTask = new LargeFileUploadTask<DriveItem>(uploadSession, stream);

    UploadResult<DriveItem> uploadResult = await largeFileUploadTask.UploadAsync();

    return uploadResult;
}
catch (ServiceException e)
{
    Log.Error(e);
    throw;
}

It is important to know that first you need to retrieve the drive ID associated to the library when creating the upload session. The drive can be retrieved from the site object, provided you load the expanded drives query option.

var siteQueryOptions = new List<QueryOption>()
{
    new QueryOption("expand", "drives")
};

var site = await this._graphClient.Sites.GetByPath(siteRelativeUrl, hostName)
    .Request(siteQueryOptions)
    .GetAsync();

string driveId = site.Drives.FirstOrDefault(d => d.WebUrl.EndsWith(workingDocumentsLibName, StringComparison.InvariantCultureIgnoreCase))?.Id;
Ciro di Marzo
  • 391
  • 2
  • 15