7

I am using an external .Net Web App and would like to know how to upload a large file to the document library using Microsoft Graph. I am able to upload up to 4mb but anything above it is throwing an error.

I know there is a createUploadSession however not sure how to implement it. Any help would greatly appreciate.

This is what I am doing to upload up to 4mb successfully:

string requestUrl =
    "https://graph.microsoft.com/v1.0/drives/{mydriveid}/items/root:/" +
    fileName + ":/content";

HttpClient Hclient = new HttpClient();

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Put, requestUrl);

message.Content = new StreamContent(file.InputStream);

client.DefaultRequestHeaders
    .TryAddWithoutValidation("Content-Type",
        "application/json; odata=verbose; charset=utf-8");

HttpResponseMessage Hresponse = await client.SendAsync(message);

//if the response is 200 then read the response and retrive the GUID!
if (Hresponse.IsSuccessStatusCode)
{
    responseString = await
    Hresponse.Content.ReadAsStringAsync();
    JObject jDataRetrieved = JObject.Parse(responseString);
    strGuid = jDataRetrieved.SelectToken("eTag").ToString();

}
Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
Binesh
  • 111
  • 1
  • 1
  • 2

2 Answers2

10

New and improved large file upload for the .NET client library

With the fluent client

Create upload session

// Create upload session 
// POST /v1.0/drive/items/01KGPRHTV6Y2GOVW7725BZO354PWSELRRZ:/SWEBOKv3.pdf:/microsoft.graph.createUploadSession
var uploadSession = await graphClient.Drive.Items[itemId].ItemWithPath("SWEBOK.pdf").CreateUploadSession().Request().PostAsync();

Create the task

// Create task
var maxChunkSize = 320 * 1024; // 320 KB - Change this to your chunk size. 5MB is the default.
var largeFileUpload = new LargeFileUpload(uploadSession, graphClient, stream, maxChunkSize);

Create upload monitor

public class MyProgress : IProgressCallback
{
    public void OnFailure(ClientException clientException)
    {
        Console.WriteLine(clientException.Message);
    }

    public void OnSuccess(DriveItem result)
    {
        Console.WriteLine("Download completed with id below");
        Console.WriteLine(result.Id);
    }

    public void UpdateProgress(long current, long max)
    {
        long percentage = (current * 100) / max ;
        Console.WriteLine("Upload in progress. " + current + " bytes of " + max + "bytes. " + percentage + " percent complete");
    }
}

Upload the file

uploadedFile = await largeFileUpload.ResumeAsync(new MyProgress());

With the HTTP client

Create upload session

// Create upload session 
// POST /v1.0/drive/items/01KGPRHTV6Y2GOVW7725BZO354PWSELRRZ:/SWEBOKv3.pdf:/microsoft.graph.createUploadSession
string uri = $"https://graph.microsoft.com/v1.0/drive/items/{itemId}:/SWEBOKv3.pdf:/microsoft.graph.createUploadSession";

HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
await graphClient.AuthenticationProvider.AuthenticateRequestAsync(httpRequestMessage);

// Read the session info from the response
var httpResponseMessage = await graphClient.HttpProvider.SendAsync(httpRequestMessage);
var content = await httpResponseMessage.Content.ReadAsStringAsync();
var uploadSession = graphClient.HttpProvider.Serializer.DeserializeObject<UploadSession>(content);

Create the task

// Create task
var maxSliceSize = 320 * 1024; // 320 KB - Change this to your chunk size. 4MB is the default.
LargeFileUploadTask<DriveItem> largeFileUploadTask = new LargeFileUploadTask<DriveItem>(uploadSession, stream, maxSliceSize);

Create upload monitor

// Setup the progress monitoring
IProgress<long> progress = new Progress<long>(progress =>
{
    Console.WriteLine($"Uploaded {progress} bytes of {stream.Length} bytes");
});

Upload the file

UploadResult<DriveItem> uploadResult = null;
try
{
    uploadResult = await largeFileUploadTask.UploadAsync(progress);

    if (uploadResult.UploadSucceeded)
    {
        Console.WriteLine($"File Uploaded {uploadResult.ItemResponse.Id}");//Sucessful Upload
    }
}
catch (ServiceException e)
{
    Console.WriteLine(e.Message);
}
Michael Mainer
  • 3,387
  • 1
  • 13
  • 32
7

You can use the client library to help you do this. From this test:

System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter();
var buff = (byte[])converter.ConvertTo(Microsoft.Graph.Test.Properties.Resources.hamilton, typeof(byte[]));
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(buff))
{
    // Get the provider. 
    // POST /v1.0/drive/items/01KGPRHTV6Y2GOVW7725BZO354PWSELRRZ:/_hamiltion.png:/microsoft.graph.createUploadSession
    // The CreateUploadSesssion action doesn't seem to support the options stated in the metadata.
    var uploadSession = await graphClient.Drive.Items["01KGPRHTV6Y2GOVW7725BZO354PWSELRRZ"].ItemWithPath("_hamilton.png").CreateUploadSession().Request().PostAsync();

    var maxChunkSize = 320 * 1024; // 320 KB - Change this to your chunk size. 5MB is the default.
    var provider = new ChunkedUploadProvider(uploadSession, graphClient, ms, maxChunkSize);

    // Setup the chunk request necessities
    var chunkRequests = provider.GetUploadChunkRequests();
    var readBuffer = new byte[maxChunkSize];
    var trackedExceptions = new List<Exception>();
    DriveItem itemResult = null;

    //upload the chunks
    foreach (var request in chunkRequests)
    {
        // Do your updates here: update progress bar, etc.
        // ...
        // Send chunk request
        var result = await provider.GetChunkRequestResponseAsync(request, readBuffer, trackedExceptions);

        if (result.UploadSucceeded)
        {
            itemResult = result.ItemResponse;
        }
    }

    // Check that upload succeeded
    if (itemResult == null)
    {
        // Retry the upload
        // ...
    }
}
Michael Mainer
  • 3,387
  • 1
  • 13
  • 32
  • Thanks Michael ! However I have to do this using the HTTP itself and still couldn't find a better solution. – Binesh Apr 11 '18 at 17:34
  • 1
    In that case, take a look at the implementation: https://github.com/microsoftgraph/msgraph-sdk-dotnet/commit/7c037cf15413b73d1ad7b52ee027a703f4b63be1 – Michael Mainer Apr 11 '18 at 19:14
  • 1
    @halllo I believe you can. I think it has been fixed. You can see an example [here](https://github.com/microsoftgraph/msgraph-sdk-dotnet/commit/7c037cf15413b73d1ad7b52ee027a703f4b63be1#diff-73f67618397ff61d1687ddfa1ce6ae91R27). – Michael Mainer Mar 20 '19 at 21:09
  • @MichaelMainer I dont understand the example in terms of custom metadata. The props is commented out. The only way I got it to work was to get the corresponding SharePointList and add a new column and then update the fields of the ListItem. – halllo Mar 25 '19 at 14:57