2012-08-09 17 views
6

Jak wysłać załącznik POST do JIRA za pomocą interfejsu JIRA REST API i HttpWebRequest w języku C#?Jak POST dołączyć do JIRA przy użyciu REST API?

Z documentation under /rest/api/2/issue/{issueIdOrKey}/attachments:

POST

Dodaj jeden lub więcej załączników do emisji.

Ten zasób oczekuje ogłoszenia wieloczęściowego. Media typu multipart/dane-formularza są zdefiniowane w RFC 1867. Większość bibliotek klienta posiada klasy, które ułatwiają obsługę wieloczęściowych postów. Na przykład w Javie biblioteka Apache HTTP Components zapewnia MultiPartEntity, która ułatwia wysyłanie wieloczęściowego testu POST.

W celu ochrony przed atakami XSRF, ponieważ ta metoda akceptuje wieloczęściowe/formularzowe dane, ma na sobie ochronę XSRF. Oznacza to, że musisz przesłać nagłówek X-Atlassian-Token: nocheck z żądaniem, w przeciwnym razie zostanie zablokowany.

Nazwa parametru wieloczęściowy/form-data, która zawiera załączniki muszą być „plik”

Prosty przykład załadować plik o nazwie „myfile.txt” do wystawienia REST-123:

pozwijane -D -u admin: admin -X POST-H "X-Atlassian-Token: nocheck" -F "[email protected]" http://myhost.test/rest/api/2/issue/TEST-123/attachments


mam

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 [email protected]" + 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(); 
} 

ale zwraca błąd 404 ...

+0

Co REST ramach używasz? –

+0

Czy możesz również podać link do cytatu z dokumentacji? –

+0

[JIRA 5.1.2 REST API] (http://docs.atlassian.com/jira/REST/latest/) –

Odpowiedz

6

rozwiązać swój problem:

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 usunąć mój poprzedni post! miło ...

+0

Dzięki! Bardzo użyteczne. Na końcu dostaję wyjątek na var data = JObject.Parse (responseData); Mówi, że to nie jest obiekt json. Ale sprawdzanie danych odpowiedzi to definitywnie. Jakieś pomysły?? – Ronald

6

W kodzie PO było kilka błędów.

Dzięki fragmentowi dostarczonemu przez @mabu i kodem, który znalazłem na http://www.briangrinstead.com/blog/multipart-form-post-in-c, oto * funkcjonalny ** blok kodu do przesłania załącznika do Jiry.

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

ja naprawdę nie chciałem mieć do czynienia z tym wszystkim boundary rzeczy, więc tu jest mój strzał w niego. Działa to przeciwko Confluence, którego interfejs API wygląda identycznie jak Jira.

Podziękowania dla Michaela Tpera z ASP.NET WebApi: how to perform a multipart post with file upload using WebApi HttpClient i Jeffa Carona (powyżej).

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); 
    } 
} 
0

jesteś też w stanie zrobić z Restsharp jak postępować

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; } 
    } 
} 

Cały kod jest na GIST https://gist.github.com/gandarez/c2c5b2b27dbaf62a0d634253529bcb59

Powiązane problemy