C#:从 Unity 上传照片到 Twitter
C#: Upload Photo To Twitter From Unity
目前我正在使用 unity。在这个项目中,我需要 post 一些带有图像的状态到 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 is longer than the maximum {0} characters.
System.Uri.EscapeDataString (System.String stringToEscape)
仅供参考,图片大小不大,只有 23 kb,图片类型为 png。
我的代码有什么问题。感谢您的帮助。
您应该只在 WWWForm 对象中添加媒体参数。根据documentation,上传媒体时:
OAuth is handled a little differently. POST or query string parameters are not used when calculating an OAuth signature basestring or signature. Only the oauth_* parameters are used.
添加参数字典中的媒体在创建签名时产生错误(由 GetHeaderWithAccessToken 制作)。
我也遇到了同样的问题。我通过减小我试图 post 的图像的大小来解决它。我不确定限制是多少,但我发现 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"...这可能是必要的也可能不是必要的,我没有试过。
我没有足够的代表发表评论,但 Antony 的代码在推动事情发展方面很有用。
问题是库使用的 Uri.EscapeDataString 方法有字符限制,所以如果你有一个大文件大小(因此是一个长的 base-64 字符串),该方法将无法为 Twitter 添加正确的 signature/timestamp 内容,因此在尝试上传媒体时会出现 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 左右并且工作正常。
祝你好运!
这是我正在使用的代码,其中包括一个带有状态的 post。我正在使用 Lets Tweet 的代码:https://www.assetstore.unity3d.com/en/#!/content/536
感谢之前 post 帮助图像上传部分正常工作的所有人。通过 Patrick 的更改,这应该允许您上传和 post 最大 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);
}
}
目前我正在使用 unity。在这个项目中,我需要 post 一些带有图像的状态到 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 is longer than the maximum {0} characters. System.Uri.EscapeDataString (System.String stringToEscape)
仅供参考,图片大小不大,只有 23 kb,图片类型为 png。
我的代码有什么问题。感谢您的帮助。
您应该只在 WWWForm 对象中添加媒体参数。根据documentation,上传媒体时:
OAuth is handled a little differently. POST or query string parameters are not used when calculating an OAuth signature basestring or signature. Only the oauth_* parameters are used.
添加参数字典中的媒体在创建签名时产生错误(由 GetHeaderWithAccessToken 制作)。
我也遇到了同样的问题。我通过减小我试图 post 的图像的大小来解决它。我不确定限制是多少,但我发现 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"...这可能是必要的也可能不是必要的,我没有试过。
我没有足够的代表发表评论,但 Antony 的代码在推动事情发展方面很有用。
问题是库使用的 Uri.EscapeDataString 方法有字符限制,所以如果你有一个大文件大小(因此是一个长的 base-64 字符串),该方法将无法为 Twitter 添加正确的 signature/timestamp 内容,因此在尝试上传媒体时会出现 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 左右并且工作正常。
祝你好运!
这是我正在使用的代码,其中包括一个带有状态的 post。我正在使用 Lets Tweet 的代码:https://www.assetstore.unity3d.com/en/#!/content/536 感谢之前 post 帮助图像上传部分正常工作的所有人。通过 Patrick 的更改,这应该允许您上传和 post 最大 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);
}
}