Question

I have a little tool built in CSOM that backs up some pertinent documents by copying them to another site collection (don't ask). Sometimes, the program hangs until I close it as it gets stuck on some files. I'm not sure how to force the program's execution if this process takes too long.

Is there a way to terminate SaveBinaryDirect? Should I check for filesize before calling the method? How can I continue processing if the Save hangs for too long?

SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
Was it helpful?

Solution

One of the ways to set a timeout is to use the Task Parallel Library (TPL). You can wrap your call in a Task and wait for it to complete based on either a time span or cancellation token.

Task upload = Task.Run(() =>
{
    SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
    SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
});

if (!upload.Wait(TimeSpan.FromMilliseconds(1000)))
{
    // handle upload failure
}

Another option is to use a more modern API. SaveBinaryDirect was introduced in 2010 over WebDAV and has been superseded with better upload methods. SharePoint/PnP recommends using the ContentStream property on FileCreationInformation (for files less than 10MB) or StartUpload, ContinueUpload, and FinishUpload on the File class (for files 10MB or greater).

By using the continuation methods, the app can recover in the middle of a failure in the event of a timeout or cancellation.

OTHER TIPS

Here is a demo for your reference, and you can use this function directly.

    /// <summary>
    /// copy a file from a document library in a siteCollection to another document library in another siteCollection
    /// </summary>
    /// <param name="sourceSiteUrl">http://sp/sites/sourceSite</param>
    /// <param name="destinationSiteUrl">http://sp/sites/destinationSite</param>
    /// <param name="host">http://sp</param>
    /// <param name="sourceListName"></param>
    /// <param name="destinationListName"></param>
    public static void CopyDocFromOneListToAnother(string sourceSiteUrl,string destinationSiteUrl, string host, string sourceListName, string destinationListName, string fileName)
    {
        sourceSiteUrl = sourceSiteUrl.EndsWith("/") ? sourceSiteUrl.Substring(0, sourceSiteUrl.Length - 1) : sourceSiteUrl;
        destinationSiteUrl = destinationSiteUrl.EndsWith("/") ? destinationSiteUrl.Substring(0, destinationSiteUrl.Length - 1) : destinationSiteUrl;
        ClientContext sourceContext = new ClientContext(sourceSiteUrl);
        ClientContext destinationContext = new ClientContext(destinationSiteUrl);
        Web sourceWeb = sourceContext.Site.RootWeb;
        Web destinationWeb = destinationContext.Site.RootWeb;

        List source = sourceWeb.Lists.GetByTitle(sourceListName);
        List destination = destinationWeb.Lists.GetByTitle(destinationListName);
        sourceContext.Load(source);
        destinationContext.Load(destination);
        sourceContext.Load(sourceWeb);
        sourceContext.ExecuteQuery();
        destinationContext.ExecuteQuery();

        FileCollection files = source.RootFolder.Files;
        Microsoft.SharePoint.Client.File file = files.GetByUrl(sourceSiteUrl+"/"+sourceListName+"/"+fileName);
        sourceContext.Load(file);
        sourceContext.ExecuteQuery();

            FileInformation fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(sourceContext, file.ServerRelativeUrl);
            string filePath = host + file.ServerRelativeUrl;
            System.IO.Stream fileStream = fileInfo.Stream;
            FileCreationInformation createFile = new FileCreationInformation();
            byte[] bufferByte = new byte[1024 * 100];
            System.IO.MemoryStream memory = new System.IO.MemoryStream();
            int len = 0;
            while ((len = fileStream.Read(bufferByte, 0, bufferByte.Length)) > 0)
            {
                memory.Write(bufferByte, 0, len);
            }
            byte[] bytes = memory.GetBuffer();

            createFile.Content = bytes;
            createFile.Url = sourceSiteUrl + "/" + destinationListName + "/" + file.Name;
            createFile.Overwrite = true;
            Microsoft.SharePoint.Client.File newFile = destination.RootFolder.Files.Add(createFile);
            newFile.ListItemAllFields.Update();
            destinationContext.ExecuteQuery();           
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top