Martin Normark's blog

Posted on by Martin H. Normark


I’ve spent some time lately, playing around with the Twitter API. And along with that belongs the TwitPic’s API. I’m using Twitter a lot, to stay in touch with tech news, other developers and just for fun. But it’s getting more and more used for a lot of different things, and I needed it to integrate with an E-commerce platform I’m developing.

The code for post a picture to TwitPic looks like this:

    /// <summary>
    /// URL for the TwitPic API's upload method
    /// </summary>
    private const string TWITPIC_UPLADO_API_URL = "http://twitpic.com/api/upload";

    /// <summary>
    /// URL for the TwitPic API's upload and post method
    /// </summary>
    private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://twitpic.com/api/uploadAndPost";

    /// <summary>
    /// Uploads the photo and sends a new Tweet
    /// </summary>
    /// <param name="binaryImageData">The binary image data.</param>
    /// <param name="tweetMessage">The tweet message.</param>
    /// <param name="filename">The filename.</param>
    /// <returns>Return true, if the operation was succeded.</returns>
    public bool UploadPhoto(byte[] binaryImageData, string tweetMessage, string filename)
    {
      // Documentation: http://www.twitpic.com/api.do
      string boundary = Guid.NewGuid().ToString();
      string requestUrl = String.IsNullOrEmpty(tweetMessage) ? TWITPIC_UPLADO_API_URL : TWITPIC_UPLOAD_AND_POST_API_URL;
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
      string encoding = "iso-8859-1";

      request.PreAuthenticate = true;
      request.AllowWriteStreamBuffering = true;
      request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
      request.Method = "POST";

      string header = string.Format("--{0}", boundary);
      string footer = string.Format("--{0}--", boundary);

      StringBuilder contents = new StringBuilder();
      contents.AppendLine(header);

      string fileContentType = GetImageContentType(filename);
      string fileHeader = String.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", "media", filename);
      string fileData = Encoding.GetEncoding(encoding).GetString(binaryImageData);

      contents.AppendLine(fileHeader);
      contents.AppendLine(String.Format("Content-Type: {0}", fileContentType));
      contents.AppendLine();
      contents.AppendLine(fileData);

      contents.AppendLine(header);
      contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "username"));
      contents.AppendLine();
      contents.AppendLine(this.Username);

      contents.AppendLine(header);
      contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "password"));
      contents.AppendLine();
      contents.AppendLine(this.Password.ToInsecureString());

      if (!String.IsNullOrEmpty(tweetMessage))
      {
        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "message"));
        contents.AppendLine();
        contents.AppendLine(tweetMessage);
      }

      contents.AppendLine(footer);

      byte[] bytes = Encoding.GetEncoding(encoding).GetBytes(contents.ToString());
      request.ContentLength = bytes.Length;

      using (Stream requestStream = request.GetRequestStream())
      {
        requestStream.Write(bytes, 0, bytes.Length);

        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
          using (StreamReader reader = new StreamReader(response.GetResponseStream()))
          {
            string result = reader.ReadToEnd();

            XDocument doc = XDocument.Parse(result);

            XElement rsp = doc.Element("rsp");
            string status = rsp.Attribute(XName.Get("status")) != null ? rsp.Attribute(XName.Get("status")).Value : rsp.Attribute(XName.Get("stat")).Value;

            return status.ToUpperInvariant().Equals("OK");
          }
        }
      }
    }

Posted on by Martin H. Normark | Posted in C# | Tagged


About Martin H. Normark

I love writing code, inventing stuff, pushing the limits, questioning why something is as it is. I write about software and programming experiments, daily code battles, specific How To posts.

  • DJ

    In your code, are you missing a function?

    string fileContentType = GetImageContentType(filename);

    GetImageContentType, I’m only familiar with this in Java.

  • DJ

    Sorry, I figured it out, however, I’m not sure how to pass binaryImageData, have an example? Thanks alot.

  • http://martinnormark.com Martin H. Normark

    You can use the System.IO.File class to do that:

    byte[] binaryImageData = File.ReadAllBytes("c:\img.jpg");
    UploadPhoto(binaryImageData, "Test", "img.jpg");

  • DJ

    One more problem.
    I’m using the following but still getting errors with
    XDocument doc = XDocument.Parse(result);

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Xml.Schema;
    using System.IO;
    using System.Xml;
    //using System.Security.Cryptography.X509Certificates;
    using System.Net.Security;

  • http://martinnormark.com Martin H. Normark

    You need to include System.Xml.Linq as well: using System.Xml.Linq;

  • Sanil

    Thanks!
    I was really stucked at the "posting the image to TwitPic" part, and was really frustated after trying many ways to do that, I even read the whole RFC # 2388 :(

    your post really helped me, and that means I’ve completed the project :)
    It’s now on codeplex http://twipli.codeplex.com

  • balu

    HI
    thanks for your code.But the
    contents.AppendLine();
    property is not available in windows mobile projects.I tried
    contents.Append("\n"); instead but its not working.
    Is there any other way.
    Regards
    Balu

  • http://martinnormark.com Martin H. Normark

    Hi Balu

    According to this: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder_members.aspx

    The AppendLine is available in the Compact Framework as well. Which version of the .Net Compact Framework are you using?