0

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

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

我认为我正在缓慢但肯定地到达那里。无论如何,我都不是这类东西的专家,但我得到了他们的其他 API 调用: http ://dev.twitpic.com/docs/2/users_show 它就像一个魅力,虽然这不是多部分的有图像的数据。

我做了一些更多的研究,并意识到我在执行 OAuth 时使用的不错的 Twitterizer 框架为我做了很多工作,即签署每个请求,并且只需要我传递一些 OAuth 令牌。所以我注意到上面为 TwitPic 上传的方法调用需要以相同的方式签名,这是困难的部分:对其进行签名,然后使用 webrequest 传递它。

这也是让我感到困惑的地方,他们说 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 内容对象似乎比我需要的手动工作要多得多。

我希望 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");
                }
            }
        }
    }
4

2 回答 2

1

修复实际上非常简单。问题是您发布到的 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 的调试器。如果有人需要它并要求,我可以做完整的代码。

于 2011-03-26T22:21:50.553 回答
0

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

}
于 2010-12-24T15:41:36.290 回答