9

C#でJIRA REST APIとHttpWebRequestを使用してJIRAに添付ファイルをPOSTする方法は?

/ rest / api / 2 / issue / {issueIdOrKey} / attachmentsの下のドキュメントから:

役職

課題に1つ以上の添付ファイルを追加します。

このリソースは、マルチパートの投稿を想定しています。メディアタイプmultipart/form-dataは、RFC 1867で定義されています。ほとんどのクライアントライブラリには、マルチパート投稿の処理を簡単にするクラスがあります。たとえば、Javaでは、Apache HTTPコンポーネントライブラリは、マルチパートPOSTの送信を簡単にするMultiPartEntityを提供します。

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/添付ファイル


私は持っています

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エラーを返します...

4

4 に答える 4

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 で以前の投稿を削除してくれました! 良い ...

于 2012-09-27T14:12:16.827 に答える
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();
        }
    }
}
于 2013-08-28T13:22:23.720 に答える
4

私は本当にそのすべてを扱いたくなかったboundaryので、ここに私のショットがあります。これは、API が Jira と同じように見えるConfluenceに対して機能します。

ASP.NET WebApiの Michael Teper に感謝: how to perform a multipart post with file upload using WebApi HttpClient and Jeff Caron (上記)。

var contents = "some long HTML that I wanted to upload";
var fileName = "Some fancy file name.html";

using (var client = new HttpClient())
{
    var uri = new Uri(URL);

    client.BaseAddress = new Uri(URL);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    client.DefaultRequestHeaders.Authorization = authorization;
    client.DefaultRequestHeaders.Add("X-Atlassian-Token", "nocheck");

    var uriPath = String.Format(AttachmentPath, pageId);

    var content = new MultipartFormDataContent();
    var fileContent = new StringContent(contents);
    // also tested to work: 
    // var fileContent = new ByteArrayContent(Encoding.UTF8.GetBytes(contents));
    content.Add(fileContent, "file", fileName);

    var response = await client.PostAsync(uriPath, content);
    if (response.IsSuccessStatusCode)
    {
        return TaskResult.Success(null, response.ReasonPhrase);
    }
    else
    {
        return TaskResult.Failure("Service responded with Status Code: " + response.StatusCode + Environment.NewLine + "Reason Phrase: " + response.ReasonPhrase);
    }
}
于 2016-08-16T12:34:33.377 に答える
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; }
    }
}

コード全体は要旨にあります https://gist.github.com/gandarez/c2c5b2b27dbaf62a0d634253529bcb59

于 2016-08-25T19:22:01.350 に答える