如何使用 Parse.com 和 PFTwitterUtils 将媒体添加到推文?
How do I add media to a Tweet using Parse.com and PFTwitterUtils?
我正在尝试点击 media/upload
端点以将图像上传到 Twitter。我正在与 Parse.com 的 PFTwitterUtils
class 签署请求。向 statuses/update
发布推文效果很好,但 media/upload
端点不断返回身份验证错误:
{
"errors": [
{
"message": "Could not authenticate you.",
"code": 32
}
]
}
我已确保我有一个有效的用户 oauth 令牌,并且 POST 正文中发送的数据是 Base64 编码的。
这是我的代码:
NSURL *url = [NSURL URLWithString:@"https://upload.twitter.com/1.1/media/upload.json"];
NSData *imageData = UIImageJPEGRepresentation(imageToUpload, 1.0);
NSString *postString = [NSString stringWithFormat:@"media=%@", [[imageData base64EncodedStringWithOptions:kNilOptions] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:@"POST"];
[[PFTwitterUtils twitter] signRequest:request];
NSLog(@"Sending twitter request...");
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"Got twitter response");
NSLog(@"Response: %@", response);
NSError *jsonSerializationError;
NSDictionary *mediaDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonSerializationError];
}];
我发现这个旧的 Parse.com 论坛 post 解释了如何使用现已弃用的 statuses/update_with_media
端点上传图像:https://parse.com/questions/how-to-upload-image-to-twitter-using-pftwitterutils-signrequest
我意识到我正在使用解析正确地签署我的请求,但端点期待一个 multipart/form-data
POST 请求。正确格式化请求后,我能够向 media/upload
端点发出有效请求并返回 media_id
值。
下面是我的最终工作代码:
NSURL *mediaURL = [NSURL URLWithString:@"https://upload.twitter.com/1.1/media/upload.json"];
UIImage *imageToUpload = [UIImage ...]
NSData *imageData = UIImageJPEGRepresentation(imageToUpload, 1.0);
NSMutableURLRequest *mediaRequest = [NSMutableURLRequest requestWithURL:mediaURL];
[mediaRequest setHTTPMethod:@"POST"];
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[mediaRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];
// body
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[mediaRequest setHTTPBody:body];
[[PFTwitterUtils twitter] signRequest:mediaRequest];
NSLog(@"Sending twitter request...");
[NSURLConnection sendAsynchronousRequest:mediaRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *mediaIdString;
if (data && !connectionError) {
NSError *jsonSerializationError;
NSDictionary *mediaDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonSerializationError];
if (!jsonSerializationError) {
mediaIdString = mediaDict[@"media_id_string"];
} else {
NSLog(@"JSON serialization error: %@", jsonSerializationError);
}
} else {
NSLog(@"Error hitting media/upload endpoint: %@", connectionError);
}
// add that media_id to a tweet using the statuses/update endpoint
}];
有用的 Twitter API 文档链接:
https://dev.twitter.com/rest/public/uploading-media
https://dev.twitter.com/rest/reference/post/media/upload
我希望这篇 post 对使用 Parse.com 平台的其他开发者有用。
这是移植到 swift 的代码,它可以工作,但请记住,您需要在状态更新中使用图像,否则不会在 Twitter 上显示。
func post (tweetString: String, tweetImage: NSData) {
let uploadUrl = NSURL(string: "https://upload.twitter.com/1.1/media/upload.json")
let uploadRequest = NSMutableURLRequest(URL: uploadUrl!)
uploadRequest.HTTPMethod = "POST"
let stringBoundary = "---------------------------14737809831466499882746641449"
let contentType = "multipart/form-data; boundary=\(stringBoundary)"
uploadRequest.addValue(contentType, forHTTPHeaderField:"Content-Type")
let body = NSMutableData()
body.appendData("--\(stringBoundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"media\"; filename=\"a.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(tweetImage)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("--\(stringBoundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadRequest.HTTPBody = body
PFTwitterUtils.twitter()!.signRequest(uploadRequest)
NSURLConnection.sendAsynchronousRequest(uploadRequest, queue: NSOperationQueue.mainQueue(),
completionHandler: { (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
print(NSString(data: data!, encoding: NSUTF8StringEncoding))
// Here you need to post the status
})
我创建了一个包含整个实现的要点,none 应该像我一样浪费时间 https://gist.github.com/ralcr/94361dcf32a9780db214
我正在尝试点击 media/upload
端点以将图像上传到 Twitter。我正在与 Parse.com 的 PFTwitterUtils
class 签署请求。向 statuses/update
发布推文效果很好,但 media/upload
端点不断返回身份验证错误:
{
"errors": [
{
"message": "Could not authenticate you.",
"code": 32
}
]
}
我已确保我有一个有效的用户 oauth 令牌,并且 POST 正文中发送的数据是 Base64 编码的。
这是我的代码:
NSURL *url = [NSURL URLWithString:@"https://upload.twitter.com/1.1/media/upload.json"];
NSData *imageData = UIImageJPEGRepresentation(imageToUpload, 1.0);
NSString *postString = [NSString stringWithFormat:@"media=%@", [[imageData base64EncodedStringWithOptions:kNilOptions] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:@"POST"];
[[PFTwitterUtils twitter] signRequest:request];
NSLog(@"Sending twitter request...");
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"Got twitter response");
NSLog(@"Response: %@", response);
NSError *jsonSerializationError;
NSDictionary *mediaDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonSerializationError];
}];
我发现这个旧的 Parse.com 论坛 post 解释了如何使用现已弃用的 statuses/update_with_media
端点上传图像:https://parse.com/questions/how-to-upload-image-to-twitter-using-pftwitterutils-signrequest
我意识到我正在使用解析正确地签署我的请求,但端点期待一个 multipart/form-data
POST 请求。正确格式化请求后,我能够向 media/upload
端点发出有效请求并返回 media_id
值。
下面是我的最终工作代码:
NSURL *mediaURL = [NSURL URLWithString:@"https://upload.twitter.com/1.1/media/upload.json"];
UIImage *imageToUpload = [UIImage ...]
NSData *imageData = UIImageJPEGRepresentation(imageToUpload, 1.0);
NSMutableURLRequest *mediaRequest = [NSMutableURLRequest requestWithURL:mediaURL];
[mediaRequest setHTTPMethod:@"POST"];
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[mediaRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];
// body
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[mediaRequest setHTTPBody:body];
[[PFTwitterUtils twitter] signRequest:mediaRequest];
NSLog(@"Sending twitter request...");
[NSURLConnection sendAsynchronousRequest:mediaRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *mediaIdString;
if (data && !connectionError) {
NSError *jsonSerializationError;
NSDictionary *mediaDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonSerializationError];
if (!jsonSerializationError) {
mediaIdString = mediaDict[@"media_id_string"];
} else {
NSLog(@"JSON serialization error: %@", jsonSerializationError);
}
} else {
NSLog(@"Error hitting media/upload endpoint: %@", connectionError);
}
// add that media_id to a tweet using the statuses/update endpoint
}];
有用的 Twitter API 文档链接:
https://dev.twitter.com/rest/public/uploading-media
https://dev.twitter.com/rest/reference/post/media/upload
我希望这篇 post 对使用 Parse.com 平台的其他开发者有用。
这是移植到 swift 的代码,它可以工作,但请记住,您需要在状态更新中使用图像,否则不会在 Twitter 上显示。
func post (tweetString: String, tweetImage: NSData) {
let uploadUrl = NSURL(string: "https://upload.twitter.com/1.1/media/upload.json")
let uploadRequest = NSMutableURLRequest(URL: uploadUrl!)
uploadRequest.HTTPMethod = "POST"
let stringBoundary = "---------------------------14737809831466499882746641449"
let contentType = "multipart/form-data; boundary=\(stringBoundary)"
uploadRequest.addValue(contentType, forHTTPHeaderField:"Content-Type")
let body = NSMutableData()
body.appendData("--\(stringBoundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"media\"; filename=\"a.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(tweetImage)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("--\(stringBoundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadRequest.HTTPBody = body
PFTwitterUtils.twitter()!.signRequest(uploadRequest)
NSURLConnection.sendAsynchronousRequest(uploadRequest, queue: NSOperationQueue.mainQueue(),
completionHandler: { (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
print(NSString(data: data!, encoding: NSUTF8StringEncoding))
// Here you need to post the status
})
我创建了一个包含整个实现的要点,none 应该像我一样浪费时间 https://gist.github.com/ralcr/94361dcf32a9780db214