使用 canvas 从 VSTS 下载 docx 文件时 WebClient DownloadFile 不工作

WebClient DownloadFile not working when download docx file with canvas from VSTS

当我使用 WebClient 从 VSTS 下载包含 'Drawing Canvas' 的 .docx 文件时,下载的 .docx 文件已损坏。 当我说损坏时,我的意思是我们无法手动打开 Word 文档,我们会收到下一条错误消息:“文件已损坏,无法打开”。

只有当 word 文件包含 canvas 并且是从 VSTS 下载时才会发生这种情况?! 如果我从 TFS2017 下载或者如果 .docx 文件不包含 Canvas 那么一切正常。

首先,我认为这个问题与编码有关,所以我测试了我在 WebClient 中找到的所有编码。 进行与编码相关的任何更改都不能解决当前问题。

此外,我尝试以不使用方法 DownloadFile 的方式更改实现,取而代之的是,我下载了字节数组并基于字节生成了 Word 文档。 随着实施方式的改变,我们遇到了与以前相同的问题。

这是代码示例:

 static void Main(string[] args)
        {
            var tfsUri = new Uri("https://.../");
            var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(tfsUri);
            var workItemStore = projectCollection.GetService<WorkItemStore>();
            var workItem = workItemStore.GetWorkItem(2);
            projectCollection.EnsureAuthenticated();
            var credentials = workItemStore.TeamProjectCollection.Credentials;
            var fileName = "D:\test_folder\files\System.Description.docx";
            var uri = workItem.Attachments[0].Uri;
            using (var request = new WebClient() { Credentials = credentials })
            {
                request.DownloadFile(uri, fileName);
            }
        }

感谢您的帮助,如果您有任何想法。

此问题不是由 docx 文件中的 canvas 引起的。如果您使用代码从 VSTS 下载该文件,即使您的 docx 文件中只有文本,该文件也应该已损坏。

这里的问题是对 VSTS 的身份验证与 TFS 不同,因此 WebClient 下载文件请求实际上在下载文件时收到 401,因为它没有下载文件所需的权限。将您的代码更新为以下内容,然后重试:

    using System;
    using Microsoft.TeamFoundation.Client;
    using Microsoft.TeamFoundation.WorkItemTracking.Client;
    using Microsoft.TeamFoundation.WorkItemTracking.Proxy;
    using System.IO;

    namespace GetAdmin
    {
        class Program
        {
            static void Main(string[] args)
            {

                TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri("https://xxx.visualstudio.com/"));
                ttpc.EnsureAuthenticated();
                WorkItemStore wistore = ttpc.GetService<WorkItemStore>();
                WorkItem wi = wistore.GetWorkItem(111);
                WorkItemServer wiserver = ttpc.GetService<WorkItemServer>();
                string tmppath = wiserver.DownloadFile(wi.Attachments[0].Id);
                string filename = @"D:\test\test.docx";
                File.Copy(tmppath,filename);
            }
        }

}