Портирование примера API-интерфейса TwitPic для C #, составные данные? - PullRequest
0 голосов
/ 27 июля 2010

Так что Twitter изменил свой способ аутентификации на OAuth , у меня, наконец, не было выбора, кроме как обновить свое приложение.У меня все работает в Твиттере (поэтому в моем приложении есть немного сохраненной информации об OAuth).Теперь я должен заставить работать API TwitPic .Нет библиотек, которые обрабатывают OAuth, который я нашел, поэтому мне приходится делать это вручную, основываясь на том, что я нашел здесь:

http://dev.twitpic.com/docs/2/upload/

Я медленно, но верно добираюсь тудаЯ думаю.Я ни в коем случае не эксперт в такого рода вещах, но я получил другой вызов API: http://dev.twitpic.com/docs/2/users_show Это работает как чудо, хотя это не многокомпонентные данные с изображением там.

Я провел еще несколько исследований и понял, что хорошая среда Twitterizer, которую я использую для выполнения OAuth, выполняет для меня большую работу, а именно, подписание каждого запроса и требует только того, чтобы я передавал несколько битов моих токенов OAuth.Итак, я заметил, что приведенный выше вызов метода для загрузки для TwitPic требует, чтобы его подписывали одинаково, что является трудной частью: подписать его и передать с помощью веб-запроса.

Что также смущает меня,они говорят, что подпись, которую часть OAuth-эха передает в заголовке, кажется, это то же самое, что создание заголовка с использованием C # System.Net.WebHeaderCollection webhc = new System.Net.WebHeaderCollection();?

Я знаю, что мне нужно сделать, каким-то образом получить запрос, вызванный смои токены OAuth (сериализованные в JSON), создайте сигнатуру, затем сделайте вызов фактическому API и передайте ему три параметра (сериализированный JSON): ключ, сообщение, файл.

Файл выводит меня из строятакже, поскольку это файл резидентной памяти, я не уверен, как передать эти данные.У меня есть фрагмент кода из старой библиотеки TwitPic:

    string fileContentType = "image/jpeg";//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);

Проблема в том, что я пытаюсь сделать все это с помощью JSON.Создание fileContentType и т. Д. Для добавления всего этого к объекту содержимого StringBuilder выглядит намного более ручной работой, чем мне нужно.

Мне бы хотелось, чтобы был TwitPic API для новой авторизации Twitter, где я передаю егофайл, сообщение и токены OAuth.Увы ... любое управление в правильном направлении будет с благодарностью.

Для полноты выложен старый метод загрузки файла, который у меня есть:

    // <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 = "image/jpeg";//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");
                }
            }
        }
    }

Ответы [ 2 ]

1 голос
/ 27 марта 2011

Исправление на самом деле очень просто. Проблема заключается в URL-адресе, который вы публикуете. В вашей строке:

private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://api.twitpic.com/1/uploadAndPost";

Вам нужно изменить на

private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://api.twitpic.com/1/uploadAndPost.xml";

OR

private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://api.twitpic.com/1/uploadAndPost.json";

Это даст вам тип ответа. Вам все еще нужно изменить часть кода, которая относится к тому, как вы используете XDocument для анализа результатов. В зависимости от URL, который вы используете выше, ответ будет либо XML, либо JSON. Ваш пример хорош для XML, однако код результатов не близок к тому, что вы ищете. Если вы хотите увидеть пример кода результата, вы можете просмотреть его на http://dev.twitpic.com/docs/1/uploadAndPost/

Например, удалите следующие строки.

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;
mediaurl = rsp.Element("mediaurl").Value;

Затем заменить на

mediaurl = doc.Element("image").Element("url").Value;

Или вы можете просто запустить отладчик для JSON. Если кому-то это нужно и запрос, я могу сделать полный код.

0 голосов
/ 24 декабря 2010

Вот вариант обертки Twipli API, который позволяет вам сделать это.Единственная проблема, с которой я столкнулся, заключается в том, что я не могу заставить его отвечать с результатом сторонних манипуляций с возвращенными данными.Однако он отправляет сообщения в Twitter и правильно загружает изображение.Так много голов лучше, чем одна, поэтому, если вы найдете решение, дайте мне знать.

protected void Button1_Click(object sender, EventArgs e)
{

    string ct = img.PostedFile.ContentType.ToString();
    string usertoken = Session["usrToken"].ToString();
    string userSecret = Session["usrSecret"].ToString();
    string conkey = Session["ConsumerKey"].ToString();
    string consecret = Session["ConsumerSecret"].ToString();
    string twitkey = Session["twitpickey"].ToString();

    string _m = m.Text; // This takes the Tweet to be posted


    HttpPostedFile myFile = img.PostedFile;
    string fileName = myFile.FileName.ToString();

    int nFileLen = myFile.ContentLength;
    byte[] myData = new byte[nFileLen];
    myFile.InputStream.Read(myData, 0, nFileLen);

    TwitPic tw = new TwitPic();
    upres.Text = tw.UploadPhoto(myData, ct, _m, fileName, twitkey, usertoken, userSecret, conkey, consecret).ToString();
    Response.Redirect("twittercb.aspx?oauth_verifier=none");
}
public class TwitPic
{
    private const string TWITPIC_UPLADO_API_URL = "http://api.twitpic.com/2/upload";
    private const string TWITPIC_UPLOAD_AND_POST_API_URL = "http://api.twitpic.com/1/uploadAndPost";
    /// 
    /// Uploads the photo and sends a new Tweet
    /// 
    /// <param name="binaryImageData">The binary image data.
    /// <param name="tweetMessage">The tweet message.
    /// <param name="filename">The filename.
    /// Return true, if the operation was succeded.
    public string UploadPhoto(byte[] binaryImageData, string ContentType, string tweetMessage, string filename, string tpkey, string usrtoken, string usrsecret, string contoken, string consecret)
    {            
        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 = ContentType;
        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}\"", "key"));
        contents.AppendLine();
        contents.AppendLine(tpkey);

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

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

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

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

        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;

        string mediaurl = "";
        try
        {
            using (Stream requestStream = request.GetRequestStream()) // this is where the bug is due to not being able to seek.
            {        
                requestStream.Write(bytes, 0, bytes.Length); // No problem the image is posted and tweet is posted
                requestStream.Close();                       
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) // here I can't get the response
                { 
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        string result = reader.ReadToEnd();

                        XDocument doc = XDocument.Parse(result); // this shows no root elements and fails here

                        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;
                        mediaurl = rsp.Element("mediaurl").Value;
                        return mediaurl;                            
                    } 
                } 

            }
        }
        catch (Exception ex)
        {
            ex.ToString();
        } 
        return mediaurl;
    }

}
...