Upload openXML Doc from memorystream to a sharepoint Document Library

Hi, I am having trouble finding correct information about how to do the above.  I am using a Lightswitch Cloud App and can pass item names to the C# handler and process to manipulate the document in a stream.  I have a requirement:
Download a Document from a SharePoint 2013 online list, remove the "Template" name to create a new document in memory.  Then get data from a few other sharepoint lists through the  list data sources that I have created (StandardListDS with StandardtList items) find tags in the document, and replace the tags with data.  Then rename the file without the "template" word and save it back to the sharepoint document library.  If the document does not exist, then it should create new, if it exists, it should check-out and then update with new version and check-in.  
I have probably rather messily got to the point where I think (not been able to check yet), I have created the doc with the updated data, by parsing the template for tags, finding out what the tags were and the data I need to replace in the document and then doing a search and replace.  But now I am stuck as all the examples I have found as to how to upload the document reference SPList (which is not available) or other methods that are not available.  Any help and pointers are very much welcomed.
I am using Visual Studio 2015 Community with the Office Tools installed for the SharePoint connectivity.

UPDATE: I think that I may have figured out the upload, but when it runs I am getting a 401 unauthorised error.  I can manually upload, but through code returns the error.  
Code used:

private ClientContext _clientContext;
_clientContext = _ctx.Application.SharePoint.GetHostWebClientContext();
private MemoryStream _doc = new MemoryStream();

// save file
                    Microsoft.SharePoint.Client.Web web = _clientContext.Web;
                    _clientContext.Load(web);
                    _clientContext.ExecuteQuery();
                    string targetFileUrl = "/" + _docFolderString + "/" +  _fileName;

                    Microsoft.SharePoint.Client.File.SaveBinaryDirect(_clientContext, targetFileUrl, _doc, true);
                    Microsoft.SharePoint.Client.File uploadedFile =  web.GetFileByServerRelativeUrl(targetFileUrl);

401 error always returns on the SaveBinaryDirect call.
vbtlAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

vbtlAuthor Commented:
Have discovered that File.SaveBinaryDirect is not supported with SharePoint Online.  
I managed to amend some code I found to upload from a memory stream.  Hopefully this will help someone else.  

       
        public Microsoft.SharePoint.Client.File UploadStreamSlicebySlice(ClientContext ctx,List libraryName, string fileName, MemoryStream stream, int fileChunkSizeInMB = 3)
        {
            // Each sliced upload requires a unique ID.
            Guid uploadId = Guid.NewGuid();

            // Get the name of the file.
            string uniqueFileName = fileName; 
            List docs = libraryName;

            // File object.
            Microsoft.SharePoint.Client.File uploadFile;

            // Calculate block size in bytes.
            int blockSize = fileChunkSizeInMB * 1024 * 1024;

            // Get the information about the folder that will hold the file.
            ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
            ctx.ExecuteQuery();

            // Get the size of the stream.
            long fileSize = stream.Length;

            if (fileSize <= blockSize)
            {
                FileCreationInformation fileInfo = new FileCreationInformation();
                fileInfo.ContentStream = stream;// fs;
                fileInfo.Url = uniqueFileName;
                fileInfo.Overwrite = true;
                uploadFile = docs.RootFolder.Files.Add(fileInfo);
                ctx.Load(uploadFile);
                ctx.ExecuteQuery();
                // Return the file object for the uploaded file.
                return uploadFile;

            }
            else
            {
                // Use large file upload approach.
                ClientResult<long> bytesUploaded = null;
                try
                {
                    using (BinaryReader br = new BinaryReader(stream))
                    {
                        byte[] buffer = new byte[blockSize];
                        Byte[] lastBuffer = null;
                        long fileoffset = 0;
                        long totalBytesRead = 0;
                        int bytesRead;
                        bool first = true;
                        bool last = false;

                        // Read data from file system in blocks. 
                        while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            totalBytesRead = totalBytesRead + bytesRead;

                            // You've reached the end of the file.
                            if (totalBytesRead == fileSize)
                            {
                                last = true;
                                // Copy to a new buffer that has the correct size.
                                lastBuffer = new byte[bytesRead];
                                Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
                            }

                            if (first)
                            {
                                using (MemoryStream contentStream = new MemoryStream())
                                {
                                    // Add an empty file.
                                    FileCreationInformation fileInfo = new FileCreationInformation();
                                    fileInfo.ContentStream = contentStream;
                                    fileInfo.Url = uniqueFileName;
                                    fileInfo.Overwrite = true;
                                    uploadFile = docs.RootFolder.Files.Add(fileInfo);

                                    // Start upload by uploading the first slice. 
                                    using (MemoryStream s = new MemoryStream(buffer))
                                    {
                                        // Call the start upload method on the first slice.
                                        bytesUploaded = uploadFile.StartUpload(uploadId, s);
                                        ctx.ExecuteQuery();
                                        // fileoffset is the pointer where the next slice will be added.
                                        fileoffset = bytesUploaded.Value;
                                    }

                                    // You can only start the upload once.
                                    first = false;
                                }
                            }
                            else
                            {
                                // Get a reference to your file.
                                uploadFile = ctx.Web.GetFileByServerRelativeUrl(docs.RootFolder.ServerRelativeUrl + System.IO.Path.AltDirectorySeparatorChar + uniqueFileName);

                                if (last)
                                {
                                    // Is this the last slice of data?
                                    using (MemoryStream s = new MemoryStream(lastBuffer))
                                    {
                                        // End sliced upload by calling FinishUpload.
                                        uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
                                        ctx.ExecuteQuery();

                                        // Return the file object for the uploaded file.
                                        return uploadFile;
                                    }
                                }
                                else
                                {
                                    using (MemoryStream s = new MemoryStream(buffer))
                                    {
                                        // Continue sliced upload.
                                        bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
                                        ctx.ExecuteQuery();
                                        // Update fileoffset for the next slice.
                                        fileoffset = bytesUploaded.Value;
                                    }
                                }
                            }

                        }
                    }
                }finally{}
            }

            return null;
        }

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft SharePoint

From novice to tech pro — start learning today.