Search code examples
c#sharepointmicrosoft-graph-apimicrosoft-graph-sdksnpoi

0 Byte file when uploading an Excel document to SharePoint online using the Microsoft Graph API


I am attempting to upload an Excel document created using the NPOI library to a SharePoint Online site using the Microsoft Graph API.

When I write the Excel file to my local machines user directory, I'm able to open the generated TestExcelUpload.xslx file without issue and see the 'ColOne', 'ColTwo', 'ColThree' entries.

However, when I upload the Excel file to the SharePoint Online site, I can see the file gets created, but when I attempt to open it I get the error message Sorry, we couldn't find 'https://company.sharepoint.com/sites/Technology/Shared Documents/Tool/Data/TestExcelUpload.xlsx'. Is it possible it was moved, renamed or deleted?. If I download the file, I can see it has a Size of 0 bytes. So I think the issue is to do with how I am doing the upload - I attempted to follow the sample from the Microsoft docs - https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?msclkid=5dab86cad12711ec91c842a089f27412&view=graph-rest-1.0&tabs=csharp.

The code below is where I am with it:

  1. Create a simple excel workbook using the NPOI library
  2. Use a file stream to write the excel workbook to my local directory (I initially just used this to rule out a problem creating the workbook with NPOI)
  3. Use the Graph API to get the document path I want to upload to, read the excel workbook into a memory stream and then use the Graph API again to upload the memory stream to the path as the content.

Would anyone be able to tell me where I might be going wrong?

public async Task ExcelUploadToSharePointTest()
{
    // 1. Create basic excel .xlsx workbook using NPOI v2.5.6  
    var testColumnData = new List<string> { "ColOne", "ColTwo", "ColThree" };

    var workbook = new XSSFWorkbook();
    var sheet1 = workbook.CreateSheet();
    var row1 = sheet1.CreateRow(0);

    for (var i = 0; testColumnData.Count > i; i++)
    {
        row1.CreateCell(i).SetCellValue(testColumnData[i]);
    }

    // 2. Write workbook to local user directory - works
    await using (var fileSteam = new FileStream($"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/TestExcelUpload.xlsx", FileMode.Create))
    {
        workbook.Write(fileSteam, true);
    }

    // 3. Write workbook to SharePoint online, by saving to memory stream and uploading using Graph API - not working
    var siteBase = await _graphServiceClient.Sites
        .GetByPath("/sites/Technology", "company.sharepoint.com")
        .Request()
        .GetAsync();

    var rootFolder = _graphServiceClient.Sites[siteBase.Id].Drive.Root;

    await using (var memoryStream = new MemoryStream())
    {
        workbook.Write(memoryStream, true);

        await rootFolder.ItemWithPath("Tool/Data/TestExcelUpload.xlsx").Content.Request().PutAsync<DriveItem>(memoryStream);
    }
}

Solution

  • It looks like that you need to set memoryStream.Position to 0.

    When you call workbook.Write(memoryStream, true) then the current position within the stream is same as the length of the stream and therefore zero bytes are uploaded.

    await using (var memoryStream = new MemoryStream())
    {
        workbook.Write(memoryStream, true);
    
        memoryStream.Position = 0;
    
        await rootFolder.ItemWithPath("Tool/Data/TestExcelUpload.xlsx").Content.Request().PutAsync<DriveItem>(memoryStream);
    }