【问题标题】:How to download the documents from Version History from a document in SharePoint如何从 SharePoint 中的文档下载版本历史记录中的文档
【发布时间】:2020-09-12 06:59:37
【问题描述】:

我想从 SharePoint 中某个文件的“版本历史记录”中下载所有文档。

我需要通过接口或 C# 代码的文档。

我也尝试过以下 API URL,但出现错误。

https://XXXX.sharepoint.com/_api/Web/GetFileByServerRelativeUrl('fileURL')/Versions

【问题讨论】:

    标签: sharepoint dynamics-crm


    【解决方案1】:

    确保您使用的是最新版本的 SharePoint Online CSOM 或至少 2017 年 9 月之后的版本。

    您可以从 Nuget 获取最新的 CSOM 版本并将其添加到您的项目中。

    完成后,您可以使用下面提到的代码下载文件的版本。根据您的环境、凭据和文件名修改它:

    var siteUrl = "https://XXXX.sharepoint.com";
    var userName = "user.name@tenantname.onmicrosoft.com";
    var password = "password";
    
    using (ClientContext context = new ClientContext(siteUrl))
    {
        SecureString securePassword = new SecureString();
        foreach (char c in password.ToCharArray())
        {
            securePassword.AppendChar(c);
        }
    
        context.AuthenticationMode = ClientAuthenticationMode.Default;
        context.Credentials = new SharePointOnlineCredentials(userName, securePassword);
    
        var file = context.Web.GetFileByServerRelativeUrl(siteUrl + "/Documents/test.docx");
        var fileVersions = file.Versions; 
        context.Load(file); 
        context.Load(fileVersions);
        context.ExecuteQuery();
    
        int index = 0;
        foreach (var version in fileVersions)
        {    
           var str = version.OpenBinaryStream();
           context.ExecuteQuery();
    
           string filename = string.Format("c:\\Downloads\\test-{0}.docx", index);
           using (var fileStream = new FileStream(filename, FileMode.OpenOrCreate))
           {
             str.Value.CopyTo(fileStream);
           }
           index++;     
        }
    
    }
    

    参考 - CSOM September 2017 update

    【讨论】:

    • 将其更改为“GetFileByUrl”,它就像一个魅力,你也可以使用 verion.VersionLabel 来存储名称为版本的文件
    【解决方案2】:

    根据MSDN,我猜你不能一次下载所有版本。您必须发送 versionid 附加在括号内,如 versions(<version id>) 才能获得特定项目。

    http://<site url>/_api/web/getfilebyserverrelativeurl('/<folder name>/<file name>')/versions(<version id>)
    

    Make sure 如果您想要次要版本,则应正确设置预期的 url。

    【讨论】:

      【解决方案3】:

      以下代码供您参考。

      string _SharePointSiteURL = @"https://lz.sharepoint.com/sites/lz";
      
      var _SharePointSiteUser = "lz@lz.onmicrosoft.com";
      var password = "Password";
      
      var localPath = @"c:\test\";
      
      var filePath="Shared Documents/ABC/Test.pdf";
      
      var securePassword = new SecureString();
      
      foreach (char c in password)
      {
          securePassword.AppendChar(c);
      }
      
      using (var clientContext = new ClientContext(_SharePointSiteURL))
      {
          var onlineCredentials = new SharePointOnlineCredentials(_SharePointSiteUser, securePassword);
          clientContext.RequestTimeout = 10000000;
          clientContext.Credentials = onlineCredentials;
          Web web = clientContext.Web;
          clientContext.Load(web, website => website.ServerRelativeUrl, website => website.Url);
          clientContext.ExecuteQuery();
      
          var spFile = clientContext.Web.GetFileByServerRelativeUrl((web.ServerRelativeUrl.EndsWith("/") ? web.ServerRelativeUrl : web.ServerRelativeUrl + "/") + filePath);
          clientContext.Load(spFile);
          FileVersionCollection versions = spFile.Versions;
          clientContext.Load(versions);
          var oldVersions = clientContext.LoadQuery(versions.Where(v => v != null));
          clientContext.ExecuteQuery();
          if (oldVersions != null)
          {
              foreach (Microsoft.SharePoint.Client.FileVersion _version in oldVersions)
              {
      
                  if (!Directory.Exists(localPath))
                  {
                      Directory.CreateDirectory(localPath);
                  }
      
                  using (var wc = new System.Net.WebClient())
                  {                       
                      wc.Credentials = onlineCredentials;
                      wc.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
                      wc.Headers["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDC)";
                      wc.DownloadFile(web.Url + "/" + _version.Url, localPath+"Test.pdf");
                  }   
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        此答案适用于可能正在寻找将下载当前文档和版本历史记录的 Powershell CSOM 脚本的其他人。

        诚然,我是一个 Powershell 新手,我很难找到一个可以从 SharePoint 下载所有当前文件及其版本的脚本。访问这些版本被证明是一个挑战,因为我尝试过的各种脚本要么提出(404)未找到或(403)禁止。我能够拼凑一个 CSOM 函数,我从另一个脚本中调用该函数,该脚本从指定的库/列表下载所有当前版本。我不能发布我的整个解决方案,因为原始脚本不是我的。你可以在这里找到它: http://www.sharepointdiary.com/2017/03/sharepoint-online-download-all-files-from-document-library-using-powershell.html#ixzz5YpC0YB00

        在上述站点的 Download-AllFilesFromLibrary 函数中,我添加了 GetFileVersions 作为 Foreach($File in $FilesColl) 循环的最后一条语句。

        正如我所说,我是 Powershell 新手,所以我确信可以对该功能进行一些改进,但它确实有效。

        Function GetFileVersions
        {
        #Get versions of specific document from library
        $fileVersions = $file.Versions;
        $ctx.Load($fileVersions);
        $ctx.ExecuteQuery();
        $vcount = $fileversions.count;
        
        If ($vcount -ne “0” ) { 
        # Download all versions of specific file as individual docs
        $fname,$fext = $file.name.split('.');   # Separate filename and extension to different variables
         foreach ($fversion in $fileVersions) {
            $str = $fversion.OpenBinaryStream(); 
            $ctx.ExecuteQuery(); 
            $dtime = $fversion.created.ToString(“u”) -replace “:”,””;   # Convert date/time created to formatted string and replace semicolons in the time with blank
            $filename =$localfolder + “\” + $fname + “~” + $dtime + “.” + $fext ; # Compose the filename as the target folder, file name + ~+ datetime created.fileextension (i.e. book~2019-02-12 153659Z.xlsx)
            $fs = New-Object IO.FileStream $filename ,'Create','Write','Read'; 
            $str.Value.CopyTo($fs); 
        
            #To use the Write-Log function below, see the script at https://gallery.technet.microsoft.com/scriptcenter/Write-Log-PowerShell-999c32d0
        
           #$vmessage = $filename + “*” + $fversion.versionlabel;  # Message to write to the log file 
          #Write-Log $vmessage;
        
            $fs.Close();
           }
                if ($fs.isdisposable) {$fs.Dispose();}  
        }
        }
        

        【讨论】:

          【解决方案5】:

          我为我开发的迁移工具提供了一个可行的解决方案。必要条件是将文件和旧版本从 SharePoint 环境迁移到另一个环境。

          要下载旧版本,请执行以下操作:

          public byte[] DownloadFile(string url, bool isHistory = false)
          {
              bool isSharepointOnline = (SPCurrentContext.Credentials is SharePointOnlineCredentials);
              HttpResponseMessage response = null;
              byte[] buffer = null;
          
              if (!isHistory)
              {
                  using (FileInformation fileInfo = File.OpenBinaryDirect(SPCurrentContext, url))
                  using (IO.MemoryStream memory = new IO.MemoryStream())
                  {
                      fileInfo.Stream.CopyTo(memory);
                      buffer = memory.ToArray();
                  }
              }
              else if (isSharepointOnline)
              {
                  using (WebClient httpClient = new WebClient())
                  {
                      httpClient.Credentials = SPCurrentContext.Credentials;
                      httpClient.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
                      httpClient.Headers["User-Agent"] = this.NONISV; // This is the TRICK!!! 
          
                      buffer = httpClient.DownloadData(string.Concat(SPCurrentContext.Url, url));
                  }
              }
              else
              {
                  using (HttpClientHandler httpHandler = new HttpClientHandler() { Credentials = SPCurrentContext.Credentials })
                  using (HttpClient client = new HttpClient(httpHandler))
                  {
                      response = client.GetAsync(string.Concat(SPCurrentContext.Url, url)).Result;
          
                      response.EnsureSuccessStatusCode();
          
                      response.Content.LoadIntoBufferAsync().Wait();
          
                      buffer = response.Content.ReadAsByteArrayAsync().Result;
                  }
              }
          
              return buffer;
          }
          

          解释:

          此方法适用于下载文件的当前版本或旧版本,因为您有文件 URL(File.ServerRelativeUrl 和 FileVersion.Url 应该可以帮助您完成此步骤)。然后,当您尝试像在“SP On-Premises”中那样从“SharePoint Online”下载文件版本时,您将收到 403 HTTP ERROR。

          当您放置一些用户代理和 X-FORMS_BASED_AUTH_ACCEPTED 标头时,该解决方案开始起作用。但是...由于 429 HTTP ERROR,您肯定会收到超时错误。 要绕过 SharePoint Throttling,您必须将您的程序注册为 SharePoint 加载项。

          为此,请转到:

          {您的共享点在线根网址}/_layouts/15/AppRegNew.aspx

          并生成您的加载项注册(有关说明和更多信息,请参阅 this linkthis link

          一旦你得到它,你可以使用 NONISV|{Your Company Name}|{Your Add-In Name}/1.0 作为 User-Agent HTTP Header。祝你好运!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-10-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-12-18
            • 2019-01-05
            • 1970-01-01
            相关资源
            最近更新 更多