简体   繁体   English

如何使用Parse.com和PFTwitterUtils向Tweet添加媒体?

[英]How do I add media to a Tweet using Parse.com and PFTwitterUtils?

I am trying to hit the media/upload endpoint to upload an image to twitter. 我正试图点击media/upload端点将图像上传到twitter。 I am signing the request with Parse.com's PFTwitterUtils class. 我正在使用Parse.com的PFTwitterUtils类签署请求。 Posting a tweet to the statuses/update works perfectly, but the media/upload endpoint keeps returning an authentication error: statuses/update发布推文工作完美,但media/upload端点不断返回身份验证错误:

{
    "errors": [
        {
            "message": "Could not authenticate you.",
            "code": 32
        }
    ]
}

I have made sure that I have a valid oauth token for the user and that the data being sent in the POST body is Base64 encoded. 我已确保为用户提供了有效的oauth令牌,并且POST主体中发送的数据是Base64编码的。

Here is my code: 这是我的代码:

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];
}];

I found this old Parse.com forum post that explained how to upload an image with the now deprecated statuses/update_with_media endpoint: https://parse.com/questions/how-to-upload-image-to-twitter-using-pftwitterutils-signrequest 我发现这个旧的Parse.com论坛帖子解释了如何使用现已弃用的statuses/update_with_media端点上传图像: httpsstatuses/update_with_media -signrequest

I realized I was signing my request properly with parse, but the endpoint is expecting a multipart/form-data POST request. 我意识到我正在使用parse正确签署我的请求,但是端点期望一个multipart/form-data POST请求。 After formatting the request properly, I was able to make a valid request to the media/upload endpoint and get a media_id value back. 正确格式化请求后,我能够向media/upload端点发出有效请求并返回media_id值。

Below is my final working code: 以下是我的最终工作代码:

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
}];

Helpful Twitter API Documentation links: 有用的Twitter API文档链接:

https://dev.twitter.com/rest/public/uploading-media https://dev.twitter.com/rest/public/uploading-media

https://dev.twitter.com/rest/reference/post/media/upload https://dev.twitter.com/rest/reference/post/media/upload

I hope this post is useful for other developers using the Parse.com platform. 我希望这篇文章对使用Parse.com平台的其他开发人员有用。

This is the code ported to swift, it works but keep in mind you need to use the image in a status update otherwise won't show on twitter. 这是移植到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

    })

I created a gist with the whole implementation, none should waste hours like i did https://gist.github.com/ralcr/94361dcf32a9780db214 我创建了一个完整实现的要点,没有人应该像我一样浪费时间https://gist.github.com/ralcr/94361dcf32a9780db214

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM