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

时间:2015-03-02 21:41:18

标签: ios twitter parse-platform twitter-oauth nsurlrequest

我正试图点击media/upload端点将图片上传到twitter。我正在与Parse.com的PFTwitterUtils课程签署该请求。向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];
}];

2 个答案:

答案 0 :(得分:0)

我发现这篇旧的Parse.com论坛帖子解释了如何使用现已弃用的statuses/update_with_media端点上传图片:https://parse.com/questions/how-to-upload-image-to-twitter-using-pftwitterutils-signrequest

我意识到我正在使用parse正确签署我的请求,但是端点期待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

我希望这篇文章对使用Parse.com平台的其他开发者有用。

答案 1 :(得分:0)

这是移植到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

    })

我在整个实施过程中创造了一个要点,没有人像我一样浪费时间https://gist.github.com/ralcr/94361dcf32a9780db214