none
How can I download a particular file from SharePoint document library using CSOM RRS feed

  • Question

  • Hi All,

    I have few file urls on different libraries or under different folder hierarchy  on SharePoint site, and I need to download only those files (not other) like given below.

    1. Http://example.com/sites/Site1/Lib1/Sample1.pdf

    2. Http://example.com/sites/Site1/Lib2/Sample2.pdf

    3. Http://example.com/sites/Site1/Lib1/Lib2/Sample3.pdf

    Is there any method to download those files directly by passing the full url, I can do it by WebClient but I am not able to do it in CSOM.

    Could  you please provide me any working code for this.


    Sonu88


    • Edited by Sonu888 Thursday, April 13, 2017 2:33 PM
    Thursday, April 13, 2017 2:30 PM

Answers

  • Hi Sou88

    You can PnP in C#.

    Just add reference to OfficeDevPnP.Core.dll to your project.

    The method is SaveFileToLocal

    The implementation copied from https://github.com/SharePoint/PnP-Sites-Core/blob/master/Core/OfficeDevPnP.Core/Extensions/FileFolderExtensions.cs

    /// <summary>
            /// Saves a remote file to a local folder
            /// </summary>
            /// <param name="web">The Web to process</param>
            /// <param name="serverRelativeUrl">The server relative url to the file</param>
            /// <param name="localPath">The local folder</param>
            /// <param name="localFileName">The local filename. If null the filename of the file on the server will be used</param>
            /// <param name="fileExistsCallBack">Optional callback function allowing to provide feedback if the file should be overwritten if it exists. The function requests a bool as return value and the string input contains the name of the file that exists.</param>
            public static void SaveFileToLocal(this Web web, string serverRelativeUrl, string localPath, string localFileName = null, Func<string, bool> fileExistsCallBack = null)
            {
                var clientContext = web.Context as ClientContext;
                var file = web.GetFileByServerRelativeUrl(serverRelativeUrl);
    
                clientContext.Load(file);
                clientContext.ExecuteQueryRetry();
    
                ClientResult<Stream> stream = file.OpenBinaryStream();
                clientContext.ExecuteQueryRetry();
    
                var fileOut = Path.Combine(localPath, !string.IsNullOrEmpty(localFileName) ? localFileName : file.Name);
    
                if (!System.IO.File.Exists(fileOut) || (fileExistsCallBack != null && fileExistsCallBack(fileOut)))
                {
                    using (Stream fileStream = new FileStream(fileOut, FileMode.Create))
                    {
                        CopyStream(stream.Value, fileStream);
                    }
                }
            }

    Call the method on your web object as follows

    SelectedWeb.SaveFileToLocal(serverRelativeUrl, Path, Filename);

    Regards

    Reshmee

    Friday, April 14, 2017 7:12 AM
  • Maybe this? I think this looks like what you are trying to do.

    It's funny because that thread links back to the C# forums: https://social.msdn.microsoft.com/Forums/en-US/dc7776e0-84b7-444c-9b82-15ff5ac5db41/write-a-stream-to-a-file?forum=csharplanguage

    • Marked as answer by Sonu888 Thursday, May 11, 2017 7:11 AM
    Thursday, April 13, 2017 4:56 PM

All replies

  • Hi Sonu88

    You can use the SharePoint PnP  PowerShell cmdlets. PnP cmdlets provide an abstraction of CSOM making it easy to interact with SharePoint on premises or online.

    $tenantAdmin  = Get-Credential -Message "Enter Administrator Credentials"
    Connect-PnPOnline -Url Http://example.com/sites/Site1 -Credentials $tenantAdmin

    Get-PnPFile -Url Site1/Lib1/Sample1.pdf -Path c:\temp  -FileName Sample1.pdf

    Get-PnPFile -Url Site1/Lib2/Sample2.pdf -Path c:\temp  -FileName Sample2.pdf

    Get-PnPFile -Url Site1/Lib1/Lib2/Sample3.pdf -Path c:\temp  -FileName Sample3.pdf

    If you are not familiar with PnP, please refer to the github site. 

    https://github.com/SharePoint/PnP-PowerShell

    Best Regards

    Reshmee

    Thursday, April 13, 2017 2:59 PM
  • Hi Reshmee,

    Can I get this in CSOM, as I am doing many other things in C# code along with this??


    Sonu88

    Thursday, April 13, 2017 4:14 PM
  • Maybe this? I think this looks like what you are trying to do.

    It's funny because that thread links back to the C# forums: https://social.msdn.microsoft.com/Forums/en-US/dc7776e0-84b7-444c-9b82-15ff5ac5db41/write-a-stream-to-a-file?forum=csharplanguage

    • Marked as answer by Sonu888 Thursday, May 11, 2017 7:11 AM
    Thursday, April 13, 2017 4:56 PM
  • Hi Sou88

    You can PnP in C#.

    Just add reference to OfficeDevPnP.Core.dll to your project.

    The method is SaveFileToLocal

    The implementation copied from https://github.com/SharePoint/PnP-Sites-Core/blob/master/Core/OfficeDevPnP.Core/Extensions/FileFolderExtensions.cs

    /// <summary>
            /// Saves a remote file to a local folder
            /// </summary>
            /// <param name="web">The Web to process</param>
            /// <param name="serverRelativeUrl">The server relative url to the file</param>
            /// <param name="localPath">The local folder</param>
            /// <param name="localFileName">The local filename. If null the filename of the file on the server will be used</param>
            /// <param name="fileExistsCallBack">Optional callback function allowing to provide feedback if the file should be overwritten if it exists. The function requests a bool as return value and the string input contains the name of the file that exists.</param>
            public static void SaveFileToLocal(this Web web, string serverRelativeUrl, string localPath, string localFileName = null, Func<string, bool> fileExistsCallBack = null)
            {
                var clientContext = web.Context as ClientContext;
                var file = web.GetFileByServerRelativeUrl(serverRelativeUrl);
    
                clientContext.Load(file);
                clientContext.ExecuteQueryRetry();
    
                ClientResult<Stream> stream = file.OpenBinaryStream();
                clientContext.ExecuteQueryRetry();
    
                var fileOut = Path.Combine(localPath, !string.IsNullOrEmpty(localFileName) ? localFileName : file.Name);
    
                if (!System.IO.File.Exists(fileOut) || (fileExistsCallBack != null && fileExistsCallBack(fileOut)))
                {
                    using (Stream fileStream = new FileStream(fileOut, FileMode.Create))
                    {
                        CopyStream(stream.Value, fileStream);
                    }
                }
            }

    Call the method on your web object as follows

    SelectedWeb.SaveFileToLocal(serverRelativeUrl, Path, Filename);

    Regards

    Reshmee

    Friday, April 14, 2017 7:12 AM
  • Hi Sou88

    You can PnP in C#.

    Just add reference to OfficeDevPnP.Core.dll to your project.

    The method is SaveFileToLocal

    The implementation copied from https://github.com/SharePoint/PnP-Sites-Core/blob/master/Core/OfficeDevPnP.Core/Extensions/FileFolderExtensions.cs

    /// <summary>
            /// Saves a remote file to a local folder
            /// </summary>
            /// <param name="web">The Web to process</param>
            /// <param name="serverRelativeUrl">The server relative url to the file</param>
            /// <param name="localPath">The local folder</param>
            /// <param name="localFileName">The local filename. If null the filename of the file on the server will be used</param>
            /// <param name="fileExistsCallBack">Optional callback function allowing to provide feedback if the file should be overwritten if it exists. The function requests a bool as return value and the string input contains the name of the file that exists.</param>
            public static void SaveFileToLocal(this Web web, string serverRelativeUrl, string localPath, string localFileName = null, Func<string, bool> fileExistsCallBack = null)
            {
                var clientContext = web.Context as ClientContext;
                var file = web.GetFileByServerRelativeUrl(serverRelativeUrl);
    
                clientContext.Load(file);
                clientContext.ExecuteQueryRetry();
    
                ClientResult<Stream> stream = file.OpenBinaryStream();
                clientContext.ExecuteQueryRetry();
    
                var fileOut = Path.Combine(localPath, !string.IsNullOrEmpty(localFileName) ? localFileName : file.Name);
    
                if (!System.IO.File.Exists(fileOut) || (fileExistsCallBack != null && fileExistsCallBack(fileOut)))
                {
                    using (Stream fileStream = new FileStream(fileOut, FileMode.Create))
                    {
                        CopyStream(stream.Value, fileStream);
                    }
                }
            }

    Call the method on your web object as follows

    SelectedWeb.SaveFileToLocal(serverRelativeUrl, Path, Filename);

    Regards

    Reshmee

    Above works flawlessly. However, missing the CopyStream function referred in forth last line. 

            private static void CopyStream(Stream source, Stream destination)
            {
                byte[] buffer = new byte[32768];
                int bytesRead;
    
                do
                {
                    bytesRead = source.Read(buffer, 0, buffer.Length);
                    destination.Write(buffer, 0, bytesRead);
                } while (bytesRead != 0);
            }

    Friday, August 16, 2019 9:17 PM