SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have decided to use the SaveBinaryDirect Method to upload documents to the sharepoint site due to not having the request/file size limitations that the client object model has.

The application does two things, Adds a folder(using the Client object model) and then uploads a selected file into the folder it has just created (using Save Binary Direct).

This works fine on my setup here. but at our clients site the folder is created fine but the file upload part returns "Unauthorized 401" error.

            SP.ClientContext ctx = new SP.ClientContext(siteurl);
            SP.Web currentWeb = ctx.Web;
            //Pass user details from config (That has owner permissions)
            ctx.Credentials = new NetworkCredential(username, password, domain);   
            //create folder method (checks if the folder exists and creates using Client Object Model)
            CreateFolder(ctx,libraryUrl,folderName)

            //Save Binary Direct Method
            string fileUrl = "/"+ libraryname + "/" + folderName + "/" + fileName;
            using (data)
            {
                //upload by passing the context, file url, file data stream, 
                //set overwrite to true
                SP.File.SaveBinaryDirect(ctx, fileUrl,data, true);
            }

This makes me think one of two things

  1. There is a setting that needs to be changed on the share point or web server in regards to the authorization/authentication.
  2. The way that i am applying the network credentials is incorrect. as it only does it for the client object model but not the save binary direct.

I'm aware that we are able to use the client object model, and we may need to do another release if its not a config/setup issue.

Anyone with more experience with this have some ideas on why its doing this?

share|improve this question
    
Is this SharePoint On-Premise or SharePoint Online? – Vardhaman Deshpande Nov 3 '13 at 14:11
    
were you able to resolve the issue? – Ryan Erickson Mar 26 '14 at 18:42
    
I did resolve the issue, but i believe it was by using the Client object model and increasing the file allocation size and a timeout on share-point server settings(not the share-point site settings). But ill be able to investigate tomorrow afternoon to confirm for you. and update the post. – Will Mar 27 '14 at 0:17

If you are using SharePoint 2013 you cannot use SaveBinaryDirect, it does not work with claims authentication. The call made by SaveBinaryDirect does not include the required authorization cookies. Details are discussed in the comments to this blog post: How to do active authentication to Office 365 and SharePoint Online

Update (July 2, 2016):

I took another look at this after seeing the comment by James Love. I'm not sure what changed but my test indicates that SaveBinaryDirect is now working with SharePoint 2013 and SharePoint Online.

Here's the code I used:

// var context = new ClientContext("http://intranet.wingtip.com/sites/demo/");
// context.Credentials = System.Net.CredentialCache.DefaultCredentials;

var context = new ClientContext("https://robwindsor2.sharepoint.com/sites/demo/");
context.Credentials = new SharePointOnlineCredentials(loginName, securePassword);

var web = context.Web;
var lib = web.Lists.GetByTitle("Documents");

context.Load(lib);
context.Load(lib.RootFolder);
context.ExecuteQuery();

var fileName = "Test.docx";
var filePath = @"C:\Users\robwindsor\Desktop\" + fileName;
using (var fs = new FileStream(filePath, FileMode.Open))
{
    Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, lib.RootFolder.ServerRelativeUrl + "/" + fileName, fs, true);
}

var query = new CamlQuery();
query.ViewXml = "<View></View>";
var files = lib.GetItems(query);

context.Load(files, c => c.Include(f => f.File));
context.ExecuteQuery();

foreach(ListItem item in files)
{
    Console.WriteLine(item.File.Name);
}

Console.WriteLine("Done");        
share|improve this answer
    
For those finding this answer now - the Client Object Model does now include a SharePointOnlineCredentials object you can use for authentication of your context. – James Love Jul 1 at 19:51

Try this:

FileCreationInformation fci = new FileCreationInformation();

fci.Content = newFile.Bytes;

fci.Url = sourceFile.Url;

fci.Overwrite = true;

Microsoft.SharePoint.Client.File replacedFile = list.RootFolder.Files.Add(fci);

context.Load(replacedFile);

context.ExecuteQuery();
share|improve this answer

I think you must add this:

ctx.RequestTimeout = 3600000;
share|improve this answer

I encountered the same problem, and found a workaround although I don't know if it is legitimate.

 System.Net.WebClient webClient = new System.Net.WebClient();

 System.Uri uri = new Uri(url); //Create a uri object with the file name but without extension

 webClient.Credentials = new NetworkCredential(username,password,domain);        //Network credentials to connect with the sharepoint server

 webClient.UploadFile(uri, "PUT", pFilePath);     //Upload File will push the file to the server
share|improve this answer

TLDR: you need to use the server relative URL, even though the context includes the site information.

I had this same issue, and resolved it by using Fiddler. When I used the client Object Model, I created the context with the site path, i.e. "https://server/sites/siteName", then

var docs = web.Lists.GetByTitle(documentLibraryName);
SP.File uploadFile = docs.RootFolder.Files.Add(newFile);
context.Load(uploadFile);
context.ExecuteQuery();

This resulted in a POST to https://<server>/sites/<siteName>/_vti_bin/client.svc/ProcessQuery the path and filename (and content) were embedded in the XML by the CSOM.

Now, the SP.File.SaveBinaryDirect signature is SaveBinaryDirect(ClientContext context, string serverRelativeUrl, Stream stream, bool overwriteIfExists) -- but the request SaveBinaryDirect(context, "/<library>/<folder>/filename", stream, true) failed with a 401 error. Look in Fiddler, and here is the request made:

PUT https://<server>/<library>/<filename>

Even though the context includes the site, you have to give it the whole path from the server root. The successful call was

SaveBinaryDirect(context, "/sites/<sitename>/<library>/<folder>/filename", stream, true)

and that results in a PUT to the correct location. The parameter is called serverRelativeUrl after all.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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