代码之家  ›  专栏  ›  技术社区  ›  Codejoy

将TwitPic API cURL示例移植到C#,多部分数据?

  •  0
  • Codejoy  · 技术社区  · 14 年前

    因此,Twitter将其身份验证方式改为 OAuth ,我最终别无选择,只能更新我的应用程序。我让Twitter的东西正常工作了(所以我在应用程序中保存了一些很好的OAuth信息)。现在我要拿到 TwitPic API再次工作。没有处理我找到的OAuth的库,因此我必须根据我在这里找到的内容手动完成它:

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

    我想,我正在缓慢但肯定地到达那里。我无论如何都不是这方面的专家,但我得到了他们的另一个API调用: http://dev.twitpic.com/docs/2/users_show 它就像一个魔咒,虽然它不是包含图像的多部分数据。

    我做了更多的研究,并意识到我正在使用的漂亮的推特器框架为我做了大量的工作,即签署每个请求,只需要我传入几位OAuth令牌。所以我注意到上面为TwitPic上传的方法调用要求以相同的方式签名,这是困难的部分:获得签名,然后使用webrequest传递。

    这也是让我困惑的地方,他们说OAuth echo部分的签名似乎是在头中传递的,这与使用C#'s创建头相同吗 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内容对象似乎比我需要的手动工作多得多。

    我希望Twitter的新授权有一个TwitPic API,在这里我传递文件、消息和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 回复  |  直到 14 年前
        1
  •  1
  •   Peter Mortensen icecrime    14 年前

    修复实际上非常简单。问题是您要发布到的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";
    

    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的调试器。如果有人需要它并提出请求,我可以完成完整的代码。

        2
  •  0
  •   Gerard Brandon    14 年前

    这里是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;
        }
    
    }
    
    推荐文章