I'm trying to develop a console application which will upload files from the users client PC to a SharePoint Online site.

I've written a version that used CSOM, but the file size is limited to 1.5Mb, so now I'm trying to use the REST API (it supports files up to 2Gb), however when I try to perform the upload all I get is 'forbidden'

I successfully obtain the form digest value, the code I have is

Public Shared Function UploadFile(baseURL As String, digest As CDigest, sourceFile As String) As Boolean

    Dim byteArray As Byte() = IO.File.ReadAllBytes(sourceFile)

    Dim folderName As String = "/TestFolder"
    Dim fileName As String = "Test.txt"
    Dim s As String = "/_api/web/GetFolderByServerRelativeUrl('[Folder]')/Files/add(url='[Filename]',overwrite=false)"
    s = s.Replace("[Folder]", folderName)
    s = s.Replace("[Filename]", fileName)

    Dim req As Net.HttpWebRequest = Net.HttpWebRequest.Create(baseURL & s)
    req.Method = "POST"
    req.Accept = "application/atom+xml"
    req.Headers.Add("X-RequestDigest", digest.Value)
    req.Headers.Add("binaryStringRequestBody", "true")
    req.Headers.Add("X-HTTP-Method", "PUT")

    req.ContentLength = byteArray.Length
    Dim ds As IO.Stream = req.GetRequestStream()

    ds.Write(byteArray, 0, byteArray.Length)


    Dim res As Net.HttpWebResponse = req.GetResponse() ' Errors here with Forbidden

    Console.WriteLine(CType(res, Net.HttpWebResponse).StatusDescription)

In fact the following CSOM examples demonstrates how to upload file those size exceeds 1,5 MB:

Example 1

Sub UploadFile(context As ClientContext, sourceFilePath As String, targetListName As String)
    Using fs As FileStream = New FileStream(sourceFilePath, IO.FileMode.Open)
        Dim fi = New FileCreationInformation()

        fi.ContentStream = fs
        fi.Url = IO.Path.GetFileName(sourceFilePath)
        fi.Overwrite = True

        Dim targetList = context.Web.Lists.GetByTitle(targetListName)
        Dim uploadFile = targetList.RootFolder.Files.Add(fi)
    End Using
End Sub

Example 2

Using File.SaveBinaryDirect Method:

Sub UploadFile(context As ClientContext, sourceFilePath As String, targetListName As String)
    Using fs As FileStream = New FileStream(sourceFilePath, IO.FileMode.Open)

        Dim targetList = context.Web.Lists.GetByTitle(targetListName)
        Dim fileUrl = String.Format("{0}/{1}", targetList.RootFolder.ServerRelativeUrl, Path.GetFileName(sourceFilePath))
        Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, fileUrl, fs, True)

    End Using
End Sub



Try this

//start out by getting a client context for o365
string o365ClientId = "o365ClientId";
string o365ClientSecret = "o365ClientSecret";
//get the Uri for the personal site
Uri siteUri = new Uri(siteUrl);
//this makes a connection to o365 using an App Only token since the user is not currently connected to o365
//NOTE:  The 5 parameter version of this method is something custom I wrote, but not needed for the general
//use case; just use the standard 3 parameter version of this method that comes out of the box.  Thanks!
var token = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUri.Authority, TokenHelper.GetRealmFromTargetUrl(siteUri),o365ClientId, o365ClientSecret).AccessToken;

string uploadUrl = siteUrl + "_api/web/lists/getByTitle('Documents')/RootFolder/Files/Add(url='" + fileName + "', overwrite=false)";
//now that we have the Url and byte array, we can make a POST request to push the data to SharePoint
    //need to get the X-RequestDigest first by doing an
    //empty post to http://<site url>/_api/contextinfo
    HttpWebRequest restRqst = (HttpWebRequest)HttpWebRequest.Create(siteUrl + "_api/contextinfo");
    restRqst.Method = "POST";
    restRqst.Accept = "application/json;odata=verbose";
    restRqst.Headers.Add("Authorization", "Bearer " + token);
    restRqst.ContentLength = 0;
    //get the response so we can read in the request digest value
    HttpWebResponse restResponse = (HttpWebResponse)restRqst.GetResponse();
    Stream postStream = restResponse.GetResponseStream();
    StreamReader postReader = new StreamReader(postStream);
    string results = postReader.ReadToEnd();
    //get the FormDigestValue node
    JavaScriptSerializer jss = new JavaScriptSerializer();
    var d = jss.Deserialize<dynamic>(results);
    string xHeader = d["d"]["GetContextWebInformation"]["FormDigestValue"];
    //now create a new request to do the actual upload
    restRqst = (HttpWebRequest)HttpWebRequest.Create(uploadUrl);
    restRqst.Method = "POST";
    restRqst.Accept = "application/json;odata=verbose";
    restRqst.Headers.Add("Authorization", "Bearer " + token);
    restRqst.Headers.Add("X-RequestDigest", xHeader);
    restRqst.ContentLength = fileBytes.Length;
    //take the document and get it ready to upload
    postStream = restRqst.GetRequestStream();
    postStream.Write(fileBytes, 0, fileBytes.Length);
    //do the upload
    restResponse = (HttpWebResponse)restRqst.GetResponse();
    //assuming it all works then we'll get a chunk of JSON back
    //with a bunch of metadata about the file we just uploaded
    postStream = restResponse.GetResponseStream();
    postReader = new StreamReader(postStream);
    results = postReader.ReadToEnd();


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.