简体   繁体   English

如何在 Azure DevOps 中以编程方式下载附件?

[英]How to programmatically download attachments in Azure DevOps?

I'm trying to programmatically download 90+ attachments from a user story in VSTS using TeamFoundation/VisualStudio C# API that I downloaded from Nuget.我正在尝试使用从 Nuget 下载的 TeamFoundation/VisualStudio C# API 以编程方式从 VSTS 中的用户故事下载 90 多个附件。 I was trying to use this example: https://intellitect.com/downloading-attachments-from-tfs/我试图使用这个例子: https : //intellitect.com/downloading-attachments-from-tfs/

However, that code seems to be out of date.但是,该代码似乎已过时。 I cannot seem to find these exact packages mentioned in article: nuget-bot.Microsoft.TeamFoundation.Client nuget-bot.Microsoft.TeamFoundation.WorkItemTracking.Client我似乎找不到文章中提到的这些确切的包: nuget-bot.Microsoft.TeamFoundation.Client nuget-bot.Microsoft.TeamFoundation.WorkItemTracking.Client

However, I downloaded TFS packages that are there such as Microsoft.TeamFoundationServer.Client and Microsoft.TeamFoundationServer.ExtendedClient but the WorkItem class does not seem to have an Attachments no more.但是,我下载了那里的 TFS 包,例如 Microsoft.TeamFoundationServer.Client 和 Microsoft.TeamFoundationServer.ExtendedClient 但 WorkItem 类似乎不再有附件了。 Does somebody know where I can find the Attachments property?有人知道我在哪里可以找到附件属性吗? I browsed the Object Browser in Visual Studio and cannot find it.我在 Visual Studio 中浏览了对象浏览器,但找不到它。 Or can you suggest an alternate solution to get attachments from a work item?或者您能否提出一种替代解决方案来从工作项中获取附件? Thanks.谢谢。

If you don't already have an access token for interacting with the API, generate one.如果您还没有用于与 API 交互的访问令牌,请生成一个。

Make an API call to get the expanded work item information.进行 API 调用以获取扩展的工作项信息。 Note the $expand=all parameter to retrieve all item details.请注意$expand=all参数以检索所有项目详细信息。

GET https://{account}.visualstudio.com/{project}/_apis/wit/workitems/115258?api-version=4.1&$expand=all

The response should look something like this (if the item has attachments).响应应如下所示(如果项目有附件)。

{
    "id": 115258,
    "rev": 4,
    "fields": {
        "System.Id": 115258,
        "System.AreaId": 2643
        ...and so on...
    },
    "relations": [
        {
            "rel": "AttachedFile",
            "url": "https://{account}.visualstudio.com/d6c4b828-0f7e-4b69-a356-a92c0ec3cd07/_apis/wit/attachments/5682f031-4b09-478c-8042-0d2a998905e4",
            "attributes": {
                "authorizedDate": "2018-04-30T19:34:09.763Z",
                "id": 2015371,
                "resourceCreatedDate": "2018-04-30T19:34:07.873Z",
                "resourceModifiedDate": "2018-04-30T19:32:16.057Z",
                "revisedDate": "9999-01-01T00:00:00Z",
                "resourceSize": 47104,
                "name": "file.jpg"
            }
        }
    ]
}

Iterate over the relations where the rel is AttachedFile and call the url to get the attachment content.遍历relAttachedFilerelations并调用url以获取附件内容。

GET https://{account}.visualstudio.com/d6c4b828-0f7e-4b69-a356-a92c0ec3cd07/_apis/wit/attachments/5682f031-4b09-478c-8042-0d2a998905e4

Sources:资料来源:

WebClient cannot authenticate to VSTS correctly. WebClient无法正确向 VSTS 进行身份验证。 Instead of using WebClient to download the file, you can use WorkItemServer.DownloadFile() method in Microsoft.TeamFoundation.WorkItemTracking.Proxy to download the file.您可以使用Microsoft.TeamFoundation.WorkItemTracking.Proxy WorkItemServer.DownloadFile()方法来下载文件,而不是使用 WebClient 下载文件。 See this thread for details.有关详细信息,请参阅此线程

You can use below sample to download the attachment for a specific work item:您可以使用以下示例下载特定工作项的附件:

Note: Install the the nuget package Microsoft.TeamFoundationServer.ExtendedClient注意:安装 nuget 包Microsoft.TeamFoundationServer.ExtendedClient

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

namespace VSTS_DownloadWITAttachment
{
    class Program
    {
        static void Main(string[] args)
        {
            TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri("https://account.visualstudio.com/"));
            ttpc.EnsureAuthenticated();
            WorkItemStore wistore = ttpc.GetService<WorkItemStore>();
            WorkItem wi = wistore.GetWorkItem(94);
            WorkItemServer wiserver = ttpc.GetService<WorkItemServer>();
            string tmppath = wiserver.DownloadFile(wi.Attachments[0].Id); //Change the number to download other attachments if there are more then one attachments for the specific work item. e.g: [1] to download the second one.
            string filename = string.Format("D:\\WITAttachments\\{0}-{1}", wi.Fields["ID"].Value, wi.Attachments[0].Name);
            File.Copy(tmppath, filename);
        }
    }
}

Then you can try to query the work items and download the attachments in a loop for each of them.然后,您可以尝试查询工作项并为每个工作项循环下载附件。 See Fetch work items with queries programatically in VSTS for details.有关详细信息,请参阅在 VSTS 中编程方式使用查询获取工作项

Below sample for your reference:以下样本供您参考:

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Proxy;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;

namespace DownloadWITAttachments
{
    class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("https://account.visualstudio.com");
            string PAT = "xxxxxxxxxxxx";
            string project = "ProjectName";

            VssBasicCredential credentials = new VssBasicCredential("", PAT);

            //create a wiql object and build our query
            Wiql wiql = new Wiql()
            {
                Query = "Select * " +
                        "From WorkItems " +
                        "Where [Work Item Type] = 'User Story' " +
                        "And [System.TeamProject] = '" + project + "' " +
                        "And [System.State] <> 'Closed' " +
                        "And [System.AttachedFileCount] > 0 " +
                        "Order By [State] Asc, [Changed Date] Desc"
            };

            //create instance of work item tracking http client
            using (WorkItemTrackingHttpClient workItemTrackingHttpClient = new WorkItemTrackingHttpClient(uri, credentials))
            {
                //execute the query to get the list of work items in the results
                WorkItemQueryResult workItemQueryResult = workItemTrackingHttpClient.QueryByWiqlAsync(wiql).Result;

                if (workItemQueryResult.WorkItems.Count() != 0)
                {
                    //Download the first attachment for each work item.
                    foreach (var item in workItemQueryResult.WorkItems)
                    {
                        TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(uri);
                        ttpc.EnsureAuthenticated();
                        WorkItemStore wistore = ttpc.GetService<WorkItemStore>();
                        Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem wi = wistore.GetWorkItem(item.Id);
                        WorkItemServer wiserver = ttpc.GetService<WorkItemServer>();                       
                        string tmppath = wiserver.DownloadFile(wi.Attachments[0].Id);
                        string filename = string.Format("D:\\temp\\vsts\\{0}-{1}", wi.Fields["ID"].Value, wi.Attachments[0].Name);
                        File.Copy(tmppath, filename);
                    }
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM