1

I have searched and found several examples of how to do this, but I can't make them work - well part of it doesn't work. I can perform the file upload, but the following attempt to change properties fail.

I'm attempting to upload a file from a base64 payload - this part works - but when I afterwards attempt to edit the properties (custom column) associated with the file, the code fails.

Here is the code (simplified for readability): (note that props is a collection of custom objects (FileProperty) with a name and a value attribute).

using (ClientContext context = new ClientContext("<sharepoint_server_url>"))
                {
                    context.Credentials = new SharePointOnlineCredentials(<usr>,<secure_pwd>);

                    using (System.IO.MemoryStream ms = new System.IO.MemoryStream(Convert.FromBase64String(<base64_content>)))
                    {
                        File.SaveBinaryDirect(context, <relative_path>, ms, true);
                    }

                    // file is uploaded - so far so good!
                    // attempt to edit properties of the file.

                    if (props != null)
                    {
                        if (props.Count > 0)
                        {
                            File newFile = context.Web.GetFileByServerRelativeUrl(<relative_path>);

                            context.Load(newFile);
                            context.ExecuteQuery();

                            newFile.CheckOut();

                            ListItem item = newFile.ListItemAllFields;

                            foreach (FileProperty fp in props)
                            {
                                item[fp.name] = fp.value;                                
                            }

                            item.Update();
                            newFile.CheckIn(string.Empty, CheckinType.OverwriteCheckIn);
                        }
                    }
                }

This code throws an exception in the part where I try to update the properties. Message: The file was not found.

Can anyone tell me what is wrong with this example or provide another example on how to do this?

Also, a question - is there a way to address a file by a unique ID which is the same regardless of where in the SharePoint server the file is located or moved to?

I hope someone can help me out - thanks :)

Aidal
  • 799
  • 4
  • 8
  • 33
  • I have also tried to add context.ExecuteQuery(); in the end, but it makes no difference. – Aidal Sep 17 '20 at 13:59
  • Also, to clarify - the file is uploaded and is visible in a browser when browsing the location. It is only the attempt to alter properties that fails due to the file not being found. – Aidal Sep 21 '20 at 07:34

2 Answers2

2

Ok, I found a solution to my problem. I don't know why this works better, it just does. For all I know, I'm doing the exact same thing, just in another way - maybe someone else who knows more about SharePoint than me (which isn't much) can explain why this works while the first example I posted doesn't.

Previous to the code shown, I ensure that <site_url> doesn't end with "/" and that <library_name> doesn't start or end with "/" and that <file_name> doesn't start or end with "/". With the code below I can uplaod a file and update properties, in my case i changed "Title" and a custom column "CustCulomnA" and it workes.

using (ClientContext context = new ClientContext(<site_url>))
                {
                    context.Credentials = new SharePointOnlineCredentials(<usr>, <secure_pwd>);

                    FileCreationInformation fci = new FileCreationInformation()
                    {
                        Url = <file_name>,
                        Content = Convert.FromBase64String(<base64_content>),
                        Overwrite = true
                    };

                    Web web = context.Web;
                    List lib = web.Lists.GetByTitle(<library_name>);
                    lib.RootFolder.Files.Add(fci);
                    context.ExecuteQuery();

                    response.message = "uploaded";

                    if (props != null)
                    {
                        if (props.Count > 0)
                        {
                            File newFile = context.Web.GetFileByUrl(<site_url> +"/"+ <library_name> + "/" + <file_name>);
                            context.Load(newFile);
                            context.ExecuteQuery();
                            newFile.CheckOut();

                            ListItem item = newFile.ListItemAllFields;

                            foreach (FileProperty fp in props)
                            {
                                item[fp.name] = fp.value;
                            }

                            item.Update();

                            newFile.CheckIn(string.Empty, CheckinType.OverwriteCheckIn);
                            context.ExecuteQuery();
Aidal
  • 799
  • 4
  • 8
  • 33
  • ,Yes, the file url struct should be http://siteurl/libraryname/filename and I saw the code snippet above, the newFile should be valid now. Glad to hear that and you could accept as answer now so that it could also help others in forum :-) – Jerry Sep 22 '20 at 01:56
1

Make sure the file server relative url is valid in this case.

For example if the complete url is:

https://zheguo.sharepoint.com/sites/test/Shared%20Documents/test.jpg

Then relative url should be

/sites/test/Shared%20Documents/test.jpg

And you can also use GetFileByUrl method, passing the complete file url like this:

               clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);
                Web web = clientContext.Web;
                clientContext.Load(web);
                clientContext.ExecuteQuery();
                File file = web.GetFileByUrl("https://zheguo.sharepoint.com/sites/test/Shared%20Documents/test.jpg");
                clientContext.Load(file);
                clientContext.ExecuteQuery();
                file.CheckOut();
                ListItem item = file.ListItemAllFields;
                item["Title"] = "Test";
                item.Update();
                file.CheckIn(string.Empty, CheckinType.OverwriteCheckIn);
                clientContext.ExecuteQuery();
            }
Jerry
  • 3,480
  • 1
  • 10
  • 12
  • My relative url is correct - it is used in the code to create the file and i write it out just to check that it is correct. But I will try to use the full path approach and see if that makes any difference. – Aidal Sep 21 '20 at 07:13
  • OK, I have tried this approach now and the result is the same, the file is uploaded just fine, but after that the file is not found. Is it a problem that I'm using the same ClientContext to retrieve the file for editing that was used to create it just higher up in the code? - I don't create a new ClientContext but reuse the one I have already. – Aidal Sep 21 '20 at 07:30
  • @Aidal, the ClientContext for uploading file and getting file should be the same. – Jerry Sep 22 '20 at 01:46