C#:从Unity上传照片到Twitter

时间:2015-03-13 02:44:30

标签: c# twitter unity3d upload media

目前我正在团结一致。在这个项目中,我需要将一些图像状态发布到twitter。但是,我将图像上传到Twitter时遇到了问题。

以下是我用来上传图片的代码:

private const string UploadMediaURL = "https://upload.twitter.com/1.1/media/upload.json";
    public static IEnumerator UploadMedia(string consumerKey, string consumerSecret, string filePath, AccessTokenResponse response){
                Dictionary<string, string> mediaParameters = new Dictionary<string, string>();
                mediaParameters.Add("media", System.Convert.ToBase64String(File.ReadAllBytes(filePath)));

                // Add data to the form to post.
                WWWForm mediaForm = new WWWForm();
                mediaForm.AddField("media", System.Convert.ToBase64String(File.ReadAllBytes(filePath)));

                print (System.Convert.ToBase64String (File.ReadAllBytes (filePath)));

                // HTTP header
                var mediaHeaders = new Hashtable();
                mediaHeaders["Authorization"] = GetHeaderWithAccessToken("POST", UploadMediaURL, consumerKey, consumerSecret, response, mediaParameters);

                WWW mw = new WWW(UploadMediaURL, mediaForm.data, mediaHeaders);
                yield return mw;

                if (!string.IsNullOrEmpty (mw.error)) {
                    Debug.Log(string.Format("PostTweet - failed. {0}"));
                } else {
                    SetMediaWeb(mw);
                }
            }

当我调用上述方法时,我得到了以下错误:

  

UriFormatException:Uri比最大{0}个字符长。   System.Uri.EscapeDataString(System.String stringToEscape)

FYI图片尺寸不大,只有23 kb,图片类型为png。

我的代码出了什么问题。谢谢你的帮助。

4 个答案:

答案 0 :(得分:2)

我也有同样的问题。我通过减少我试图发布的图像的大小来解决它。我不确定限制是什么,但我发现256 * 256 jpg工作正常。

我也注意到你的代码与我的代码有点不同。这是我的代码

Dictionary<string, string> parameters = new Dictionary<string, string>();
string encoded64ImageData = ImageToBase64( imageData );
parameters.Add("media_data", encoded64ImageData );

// Add data to the form to post.
WWWForm form = new WWWForm();
form.AddField( "media_data", encoded64ImageData );

// HTTP header
Dictionary<string, string> headers = new Dictionary<string, string>();
string url = UploadMediaURL;
string auth = GetHeaderWithAccessToken("POST", url, consumerKey, consumerSecret, accessToken, parameters);
headers.Add( "Authorization", auth );
headers.Add( "Content-Transfer-Encoding", "base64" );

WWW web = new WWW(url, form.data, headers);
yield return web;

Twitter文档说你需要在提交64位编码媒体时使用media_data。 media/upload

我还读到你需要在提交64位数据表格时定义“Content-Transfer-Encoding = base64”......这可能是也可能没有必要,我没有尝试过。

答案 1 :(得分:2)

我没有足够的代表发表评论,但Antony的代码对于让事情发生变化非常有用。

问题是库使用的Uri.EscapeDataString方法有字符限制,所以如果你有一个大的文件大小(因此有一个长的base-64字符串),那么该方法将无法添加正确的签名/时间戳为Twitter的内容,因此在尝试上传媒体时会产生401。

因此,一个简单的解决方法是将base64字符串拆分为较小的块,然后将它们分开,然后将它们拼凑在一起以进行最终的POST。 下面的代码实际上取自另一个关于Uri.EscapeDataString的SO问题。 在构建表单对象时,简单地调用此方法而不是Uri.EscapeDataString,你应该都很好。

private static string EscapeString(string originalString)
    {
        int limit = 2000;

        StringBuilder sb = new StringBuilder();
        int loops = originalString.Length / limit;

        for (int i = 0; i <= loops; i++)
        {
            if (i < loops)
            {
                sb.Append(Uri.EscapeDataString(originalString.Substring(limit * i, limit)));
            }
            else
            {
                sb.Append(Uri.EscapeDataString(originalString.Substring(limit * i)));
            }
        }
        return sb.ToString();
    }

我一直在我的最新游戏中使用它,并且它允许玩家轻松上传动画GIF,并且尚未发现任何问题,我们的最大文件大小约为2mb并且工作正常。

祝你好运!

答案 2 :(得分:0)

您应该仅在WWWForm对象中添加media参数。根据{{​​3}},在上传媒体时:

  

OAuth的处理方式略有不同。计算OAuth签名基本字符串或签名时,不使用POST或查询字符串参数。仅使用 oauth _ * 参数。

在参数字典中添加媒体是在创建签名期间生成错误(由GetHeaderWithAccessToken制作)。

答案 3 :(得分:0)

这是我工作的代码,包括一个有状态的帖子。我正在使用Lets Tweet的代码:https://www.assetstore.unity3d.com/en/#!/content/536 感谢之前发布的所有人都帮助让图片上传部分正常运行。通过Patrick的更改,您可以上传和发布最大5MB的图像或媒体文件。

    Dictionary<string, string> mediaParameters = new Dictionary<string, string> ();
            string mediaString = System.Convert.ToBase64String (File.ReadAllBytes (filePath));
            mediaParameters.Add ("media_data", mediaString);
            mediaParameters.Add ("status", text);

            // Add data to the form to post.
            WWWForm mediaForm = new WWWForm ();
            mediaForm.AddField ("media_data", mediaString);
            mediaForm.AddField ("status", text);

//          Debug.Log (System.Convert.ToBase64String (File.ReadAllBytes (filePath)));

            // HTTP header
            Dictionary<string, string> mediaHeaders = new Dictionary<string, string> ();
            string url = UploadMediaURL;
            string auth = GetHeaderWithAccessToken ("POST", UploadMediaURL, consumerKey, consumerSecret, response, mediaParameters);
            mediaHeaders.Add ("Authorization", auth);
            mediaHeaders.Add ("Content-Transfer-Encoding", "base64");

            WWW mw = new WWW (UploadMediaURL, mediaForm.data, mediaHeaders);
            yield return mw;

            string mID = Regex.Match(mw.text, @"(\Dmedia_id\D\W)(\d*)").Groups[2].Value;

            Debug.Log ("response from media request : " + mw.text);

            Debug.Log ("mID = " + mID);

            if (!string.IsNullOrEmpty (mw.error)) {
                Debug.Log (string.Format ("PostTweet - failed. {0}\n{1}", mw.error, mw.text));
                callback (false);
            } else {
                string error = Regex.Match (mw.text, @"<error>([^&]+)</error>").Groups [1].Value;

                if (!string.IsNullOrEmpty (error)) {
                    Debug.Log (string.Format ("PostTweet - failed. {0}", error));
                    callback (false);
                } else {
                    callback (true);
                }
            }

            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("status", text);
            parameters.Add ("media_ids", mID);

            // Add data to the form to post.
            WWWForm form = new WWWForm();
            form.AddField("status", text);
            form.AddField ("media_ids", mID);

            // HTTP header
            var headers = new Dictionary<string, string>();
            headers["Authorization"] = GetHeaderWithAccessToken("POST", PostTweetURL, consumerKey, consumerSecret, response, parameters);

            WWW web = new WWW(PostTweetURL, form.data, headers);
            yield return web;

            if (!string.IsNullOrEmpty(web.error))
            {
                Debug.Log(string.Format("PostTweet - failed. {0}\n{1}", web.error, web.text));
                callback(false);
            }
            else
            {
                string error = Regex.Match(web.text, @"<error>([^&]+)</error>").Groups[1].Value;

                if (!string.IsNullOrEmpty(error))
                {
                    Debug.Log(string.Format("PostTweet - failed. {0}", error));
                    callback(false);
                }
                else
                {
                    callback(true);
                }
            }