如何使用REST API将附件发布到JIRA?

时间:2012-08-09 15:01:59

标签: c# rest jira

如何在C#中使用JIRA REST API和HttpWebRequest将附件发布到JIRA?

来自documentation under /rest/api/2/issue/{issueIdOrKey}/attachments

  

POST

     

为问题添加一个或多个附件。

     

此资源需要多部分帖子。媒体类型的multipart / form-data在RFC 1867中定义。大多数客户端库都有类,使得处理多部分帖子变得简单。例如,在Java中,Apache HTTP Components库提供了一个MultiPartEntity,使得提交多部分POST变得简单。

     

为了防止XSRF攻击,因为此方法接受multipart / form-data,所以它具有XSRF保护。这意味着您必须提交X-Atlassian-Token标头:nocheck请求,否则将被阻止。

     

包含附件的multipart / form-data参数的名称必须是“file”

     

上传名为“myfile.txt”的文件以发布REST-123的简单示例:

     

curl -D- -u admin:admin -X POST -H“X-Atlassian-Token:nocheck”-F“file=@myfile.txt”http://myhost.test/rest/api/2/issue/TEST-123/attachments


我有

foreach (JIRAAttachments attachm in attachments.attachments)
{
    request = HttpWebRequest.Create(
                  logInformation.GetUri() + "/rest/api/2/issue/" + key + "/attachments"
              ) as HttpWebRequest;
    request.Headers.Add("Authorization: Basic " + logInformation.GetEncodeAuthentication());
    request.Method = "POST";
    request.ContentType = "multipart/form-data";
    request.Headers.Add("X-Atlassian-Token: nocheck file=@" + Path.GetFullPath(@"..\Attachments\" + attachm.filename));
    request.KeepAlive = true;
    request.Proxy = wp;
    response = (HttpWebResponse)request.GetResponse();
    Stream s = response.GetResponseStream();
    FileStream fs = new FileStream(Path.GetFullPath(@"..\Attachments\" + attachm.filename), FileMode.Open);
    byte[] write = new byte[256];
    int count = fs.Read(write, 0, write.Length);
    while (count > 0)
    {
        s.Write(write, 0, count);
        count = fs.Read(write, 0, write.Length);
    }
    fs.Close();
    s.Close();
    response.Close();
}

但它返回404错误...

3 个答案:

答案 0 :(得分:6)

解决了你的问题:

var boundary = string.Format("----------{0:N}", Guid.NewGuid());
System.IO.MemoryStream content = new MemoryStream();
var writer = new StreamWriter(content);
foreach (var att in attachments)
{

    writer.WriteLine("--{0}", boundary);
    writer.WriteLine("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"", "file", Path.GetFileName(att["filename"]));
    writer.WriteLine("Content-Type: {0}", att.ContentType);
    writer.WriteLine();
    writer.Flush();
    att.Stream.CopyTo(content);
    writer.WriteLine();
}
writer.WriteLine("--" + boundary + "--");
writer.Flush();
content.Seek(0, SeekOrigin.Begin);


HttpWebRequest oRequest = null;
oRequest = (HttpWebRequest)HttpWebRequest.Create(string.Format(RestBaseURI + "issue/{0}/attachments", item.Key));
oRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
oRequest.Method = "POST";
oRequest.Headers.Add("Authorization", AuthData);
oRequest.Headers.Add("X-Atlassian-Token", "nocheck");
oRequest.UseDefaultCredentials = true;
oRequest.KeepAlive = true;
oRequest.ContentLength = content.Length;

using (var oStream = oRequest.GetRequestStream())
{
    content.CopyTo(oStream);
}

using (var oResponse = (HttpWebResponse)oRequest.GetResponse())
{
    using (var reader = new StreamReader(oResponse.GetResponseStream()))
    {
        var responseData = reader.ReadToEnd();
        var data = JObject.Parse(responseData);
    }
}

PS:thanks2mod删除我以前的帖子!很好......

答案 1 :(得分:6)

OP的代码中有一些错误。

使用@mabu提供的代码段和我在http://www.briangrinstead.com/blog/multipart-form-post-in-c上找到的代码,这里有一个*功能**代码块上传附件到Jira。

public bool AddAttachments(string issueKey, IEnumerable<string> filePaths)
{
    string restUrl = Jira.FormatRestUrl(m_JiraId, true);
    string issueLinkUrl = String.Format("{0}/issue/{1}/attachments", restUrl, issueKey);

    var filesToUpload = new List<FileInfo>();
    foreach (var filePath in filePaths)
    {
        if (!File.Exists(filePath))
        {
            Jira.LogError("File '{0}' doesn't exist", filePath);
            return false;
        }

        var file = new FileInfo(filePath);
        if (file.Length > 10485760) // TODO Get Actual Limit
        {
            Jira.LogError("Attachment too large");
            return false;

        }

        filesToUpload.Add(file);
    }

    if (filesToUpload.Count <= 0)
    {
        Jira.LogWarning("No file to Upload");
        return false;
    }

    return PostMultiPart(issueLinkUrl, filesToUpload);
}

private Boolean PostMultiPart(string restUrl, IEnumerable<FileInfo> filePaths)
{
    HttpWebResponse response = null;
    HttpWebRequest request = null;

    try
    {
        var boundary = string.Format("----------{0:N}", Guid.NewGuid());
        var content = new MemoryStream();
        var writer = new StreamWriter(content);

        foreach (var filePath in filePaths)
        {
            var fs = new FileStream(filePath.FullName, FileMode.Open, FileAccess.Read);
            var data = new byte[fs.Length];
            fs.Read(data, 0, data.Length);
            fs.Close();

            writer.WriteLine("--{0}", boundary);
            writer.WriteLine("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"", filePath.Name);
            writer.WriteLine("Content-Type: application/octet-stream");
            writer.WriteLine();
            writer.Flush();

            content.Write(data, 0, data.Length);

            writer.WriteLine();
        }

        writer.WriteLine("--" + boundary + "--");
        writer.Flush();
        content.Seek(0, SeekOrigin.Begin);

        request = WebRequest.Create(restUrl) as HttpWebRequest;
        if (request == null)
        {
            Jira.LogError("Unable to create REST query: {0}", restUrl);
            return false;
        }

        request.Method = "POST";
        request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
        request.Accept = "application/json";
        request.Headers.Add("Authorization", "Basic " + m_EncodedCredential);
        request.Headers.Add("X-Atlassian-Token", "nocheck");
        request.ContentLength = content.Length;

        using (Stream requestStream = request.GetRequestStream())
        {
            content.WriteTo(requestStream);
            requestStream.Close();
        }

        using (response = request.GetResponse() as HttpWebResponse)
        {
            if (response.StatusCode != HttpStatusCode.OK)
            {
                var reader = new StreamReader(response.GetResponseStream());
                Jira.LogError("The server returned '{0}'\n{1}", response.StatusCode, reader.ReadToEnd());
                return false;
            }

            return true;
        }
    }
    catch (WebException wex)
    {
        if (wex.Response != null)
        {
            using (var errorResponse = (HttpWebResponse)wex.Response)
            {
                var reader = new StreamReader(errorResponse.GetResponseStream());
                Jira.LogError("The server returned '{0}'\n{1}).", errorResponse.StatusCode, reader.ReadToEnd());
            }
        }

        if (request != null)
        {
            request.Abort();
        }

        return false;
    }
    finally
    {
        if (response != null)
        {
            response.Close();
        }
    }
}

答案 2 :(得分:0)

您还可以使用Restsharp,如下所示

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Jira
using RestSharp;
using RestSharp.Authenticators;

namespace Jira
{
    class Program
    {
      static void Main(string[] args)
      {
        var client = new RestClient("http://{URL}/rest/api/2");
        var request = new RestRequest("issue/", Method.POST);

        client.Authenticator = new HttpBasicAuthenticator("user", "pass");

        var issue = new Issue
        {
            fields =
                new Fields
                {
                    description = "Issue Description",
                    summary = "Issue Summary",
                    project = new Project { key = "KEY" }, 
                    issuetype = new IssueType { name = "ISSUE_TYPE_NAME" }
                }
        };

        request.AddJsonBody(issue);

        var res = client.Execute<Issue>(request);

        if (res.StatusCode == HttpStatusCode.Created)
        {
            Console.WriteLine("Issue: {0} successfully created", res.Data.key);

            #region Attachment            
            request = new RestRequest(string.Format("issue/{0}/attachments", res.Data.key), Method.POST);

            request.AddHeader("X-Atlassian-Token", "nocheck");

            var file = File.ReadAllBytes(@"C:\FB_IMG_1445253679378.jpg");

            request.AddHeader("Content-Type", "multipart/form-data");
            request.AddFileBytes("file", file, "FB_IMG_1445253679378.jpg", "application/octet-stream");

            var res2 = client.Execute(request);

            Console.WriteLine(res2.StatusCode == HttpStatusCode.OK ? "Attachment added!" : res2.Content);
            #endregion
        }
        else
            Console.WriteLine(res.Content);
      }
    }

    public class Issue
    {
        public string id { get; set; }
        public string key { get; set; }
        public Fields fields { get; set; }
    }

    public class Fields
    {
        public Project project { get; set; }
        public IssueType issuetype { get; set; }
        public string summary { get; set; }
        public string description { get; set; }        
    }

    public class Project
    {
        public string id { get; set; }
        public string key { get; set; }
    }

    public class IssueType
    {
        public string id { get; set; }
        public string name { get; set; }
    }
}

整个代码在gist https://gist.github.com/gandarez/c2c5b2b27dbaf62a0d634253529bcb59