Need example to create thread with attachment

Hi Team,

We are using Forum Thread resd endpoint to create thread.

Using the REST api i.e 


It is working fine if I create only thread without attachments.

var values = new NameValueCollection();
values["Subject"] = "Attachment thread";
values["Body"] = "All about Attachments";

But If I try to use below fields i.e


values["FileData"] = BytesData;

It is not working. Could you please give me one sample example how to achieve thread with attachment functionality?

Thanks in advance.

  • I also need this functionality for group avatar saving in previous version of Zimbra Community 7.6 ; Though in new version 8.0 of Zimbra Community group avatar rest endpoint comes out of the box..

  • In reply to Harsh Baid:

    Adding more information for using the forum thread from client side:

    I believe you need to pass the File related parameters in combination such as:

    1. Passing only 'FileData' parameter


    2. Passing both 'Filename' and 'FileUploadContext'

  • In reply to Harsh Baid:

    Actually in the rest end point values["FileName"] and values["FileData"]  are available.

    But there is no example how to use this in Code. Could anyone please provide me sample code to use.

  • In reply to KrishnaSandeep:

    There is one documentation available for uploading files using REST API.

    check this link -

    Code sample link -

  • In reply to Harsh Baid:

    I got a chance to see those links.But no where mentioned about values["FileName"] and values["FileData"].

    With out those inputs how can we create attachments using REST API.

  • In reply to KrishnaSandeep:

    The two links mentioned by are indeed still relevant for forum threads. Additionally, please see:

  • In reply to Michael Monteleone:


    values["FileData"] = BytesData;

    FileData has to take bytes data as input, but when I am giving bytes data as input I got an error stating that "Can not implicitly convert type byte[] to string".

    Can you please explain, it is high priority for me.



  • In reply to KrishnaSandeep:

    Can you paste in a code snippet?

  • In reply to Luke D:

    var requestUrlForums = "";
                var values = new NameValueCollection();
    System.IO.FileStream fs = new System.IO.FileStream("C:\\Krishna\\Steps to order the left navigation links.docx", System.IO.FileMode.Open, System.IO.FileAccess.Read);
                System.IO.BinaryReader binaryReader = new System.IO.BinaryReader(fs);
                long byteLength = new System.IO.FileInfo("C:\\Krishna\\Steps to order the left navigation links.docx").Length;
                byte[] fileContents = binaryReader.ReadBytes((Int32)byteLength);
                values["FileData"] = fileContents;
    var xml = Encoding.UTF8.GetString(webClient.UploadValues(requestUrlForums, values));
  • In reply to KrishnaSandeep:

    Hi Luke,

    Provided the code.

  • In reply to KrishnaSandeep:

    public static ThreadResponse CreateThreadWithAttachment(int forumId, NameValueCollection values, string userToImpersonate, byte[] fileData, string fileName, string fileType)
                ThreadResponse response = new ThreadResponse();
                    var postData = string.Empty;
                    var boundary = Guid.NewGuid().ToString().Replace("-", "");

                    var items = values.AllKeys.SelectMany(values.GetValues, (k, v) => new { key = k, value = v });

                    foreach (var val in items)
                        postData += String.Format(get_data_multipart_formdata(boundary), val.key, val.value);

                    postData += String.Format(get_file_multipart_formdata(boundary), fileName, fileType);

                    var url = String.Format("{0}/api.ashx/v2/forums/{1}/threads.xml", RequestUrl.Trim(), forumId);

                    var request = WebRequest.Create(url) as HttpWebRequest;
                    request.Headers.Add("Rest-User-Token", AdminKeyBase64);
                    request.Headers.Add("Rest-Impersonate-User", userToImpersonate);
                    request.ContentType = "multipart/form-data; boundary=" + boundary;
                    request.Method = "POST";

                    byte[] bytes = Encoding.UTF8.GetBytes(postData);
                    var endingBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
                    byte[] allBytes = new byte[bytes.Length + fileData.Length + endingBoundaryBytes.Length];
                    bytes.CopyTo(allBytes, 0);
                    fileData.CopyTo(allBytes, bytes.Length);
                    endingBoundaryBytes.CopyTo(allBytes, bytes.Length + fileData.Length);

                    request.ContentLength = allBytes.Length;

                    using (var requestStream = request.GetRequestStream())
                        requestStream.Write(allBytes, 0, allBytes.Length);

                    using (var webResponse = request.GetResponse())
                        response = ThreadParser.ParseThreadReponse(webResponse.GetResponseStream());
                catch (WebException ex)
                    //Catch Some Error

                return response;

    private static string get_data_multipart_formdata(string boundary)
                var boundaryData = "--" + boundary + "\r\n";

                return boundaryData + "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";

            private static string get_file_multipart_formdata(string boundary)
                var boundaryData = "--" + boundary + "\r\n";

                return boundaryData + "Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\r\nContent-Type: {1}\r\n\r\n";
  • In reply to Tony Triguero:

    - Take a look at what Tony posted above - you need to use the multipart/form-data with a boundary to submit the binary data, you can't just add it directly into the NameValueCollection

    What Tony posted is pretty much what is outlined in the documentation links provided in the replies above a while back.  

  • In reply to Tony Triguero:

    Hi Tony,

    That's fine.

    When I copied this code, I got the error messages at "ThreadParser" and "ThreadResponse".

    Do I need to add any assembly references?

  • In reply to KrishnaSandeep:

    ThreadParser is a custom class that parses the response.  And ThreadResponse is a custom Rest Response object.  So those errors are expected if you are copying the exact code.

  • In reply to Tony Triguero:


    Could you please provide the definitions of both ThreadParser and ThreadResponse.So I will give a try.