Uploading a media with a tweet in iOS without using the social framework . Just OAuth

THEBrianAsh
@THEBrianAsh Brian Ash

This is the code I have currently handling it. When I submit the tweet, everything looks fine on my end, but no text or image appears on Twitter. No tweet is actually made.

  1. - (NSString ) _uploadImage:(UIImage *)image withStatus:(NSString)status accessToken:(OAToken*)_token requestType:(MGTwitterRequestType)requestType responseType:(MGTwitterResponseType)responseType
  2. {
  3.     NSURL *finalURL = [NSURL URLWithString:@"https://api.twitter.com/1.1/statuses/update_with_media.json"];
  4.     if (!finalURL)
  5.     {
  6.         return nil; 
  7.     }
  8.     OAMutableURLRequest *theRequest = [[[OAMutableURLRequest alloc] initWithURL:finalURL
  9.                                                                        consumer:self.consumer
  10.                                                                           token:_accessToken
  11.                                                                           realm: nil
  12.                                                               signatureProvider:nil] autorelease];
  13.     NSData *imageData = UIImagePNGRepresentation(image);
  14.     [theRequest setHTTPMethod:@"POST"];
  15.     [theRequest setTimeoutInterval:120];
  16.     [theRequest setHTTPShouldHandleCookies:NO];
  17.     // Set headers for client information, for tracking purposes at Twitter.
  18.     [theRequest setValue:_clientName    forHTTPHeaderField:@"X-Twitter-Client"];
  19.     [theRequest setValue:_clientVersion forHTTPHeaderField:@"X-Twitter-Client-Version"];
  20.     [theRequest setValue:_clientURL     forHTTPHeaderField:@"X-Twitter-Client-URL"];
  21.     NSString *boundary = @"--0246824681357ACXZabcxyz";
  22.     NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
  23.     [theRequest setValue:contentType forHTTPHeaderField:@"content-type"];
  24.  
  25.    // NSMutableData *body = [NSMutableData dataWithLength:0];
  26.      NSMutableData *body = [NSMutableData data];
  27.     [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  28.     // status
  29.     [body appendData:[[NSString stringWithFormat:@"--%@\r\n\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
  30.     [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"status\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  31.     [body appendData:[[NSString stringWithFormat:@"%@",status] dataUsingEncoding:NSUTF8StringEncoding]];
  32.     [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  33.     // media 
  34.     [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
  35.     [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"media[]\"; filename=\"1.png\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  36.     [body appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  37.     //[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  38.     [body appendData:[NSData  dataWithData:imageData]];
  39.     [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  40.     //
  41.     [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];    // --------------------------------------------------------------------------------
  42.     // modificaiton from the base clase
  43.     // our version "prepares" the oauth url request
  44.     // --------------------------------------------------------------------------------
  45.     [theRequest prepare];
  46.  
  47.     [theRequest setHTTPBody:body];
  48.  
  49.     NSLog(@"url is %@",theRequest.URL);
  50.     // Create a connection using this request, with the default timeout and caching policy,
  51.     // and appropriate Twitter request and response types for parsing and error reporting.
  52.     MGTwitterHTTPURLConnection *connection;
  53.     connection = [[MGTwitterHTTPURLConnection alloc] initWithRequest:theRequest
  54.                                                             delegate:self
  55.                                                          requestType:requestType
  56.                                                         responseType:responseType];
  57.  
  58.     if (!connection) {
  59.         return nil;
  60.     } else {
  61.         [_connections setObject:connection forKey:[connection identifier]];
  62.         [connection release];
  63.     }
  64.  
  65.     return [connection identifier];  
  66. }
1 year 8 weeks ago

Replies

theSeanCook
@theSeanCook Sean Cook

I highly recommend that you migrate to the native frameworks, and then follow the instructions at Posting images using SLRequest. Both TWRequest and SLRequest can be used for image uploads, and don't require you to manually configure the request's HTTP body.

As to your code:
* What HTTP response status code message are you receiving after POSTing? The different status codes will help you understand if this is an OAuth issue, or if it's some other type of error.
* It appears that your boundary variable includes '--', yet when building the body you're also including the '--' in your stringWithFormat calls. At first glance, I'd say that this is your issue.

-Sean

1 year 8 weeks ago
THEBrianAsh
@THEBrianAsh Brian Ash

Sean Cook... Genius? I think so.. Problem solved. Thanks a million

1 year 8 weeks ago
foo_mobi
@foo_mobi Foo

check this one, it worked for me:
NSURL *finalURL = [NSURL URLWithString:@"https://upload.twitter.com/1/statuses/update_with_media.json"];
if (!finalURL)
{
return nil;
}
OAMutableURLRequest *theRequest = [[[OAMutableURLRequest alloc] initWithURL:finalURL
consumer:self.consumer
token:_accessToken
realm: nil
signatureProvider:nil] autorelease];
[theRequest setHTTPMethod:@"POST"];
[theRequest setTimeoutInterval:120];
[theRequest setHTTPShouldHandleCookies:NO];
// Set headers for client information, for tracking purposes at Twitter.
[theRequest setValue:_clientName forHTTPHeaderField:@"X-Twitter-Client"];
[theRequest setValue:_clientVersion forHTTPHeaderField:@"X-Twitter-Client-Version"];
[theRequest setValue:_clientURL forHTTPHeaderField:@"X-Twitter-Client-URL"];
NSString *boundary = @"--0246824681357ACXZabcxyz";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[theRequest setValue:contentType forHTTPHeaderField:@"content-type"];

// NSMutableData *body = [NSMutableData dataWithLength:0];
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"status\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@",status] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
// media
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"media[]\"; filename=\"1.png\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
//[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
//
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; // --------------------------------------------------------------------------------
// modificaiton from the base clase
// our version "prepares" the oauth url request
// --------------------------------------------------------------------------------
[theRequest prepare];

[theRequest setHTTPBody:body];

// Create a connection using this request, with the default timeout and caching policy,
// and appropriate Twitter request and response types for parsing and error reporting.
MGTwitterHTTPURLConnection *connection;
connection = [[MGTwitterHTTPURLConnection alloc] initWithRequest:theRequest
delegate:self
requestType:requestType
responseType:responseType];

if (!connection) {
return nil;
} else {
[_connections setObject:connection forKey:[connection identifier]];
[connection release];
}

return [connection identifier];

you have to remove line 27, that's it, hope it works for you,

Hassan

1 year 8 weeks ago
chandaboy
@chandaboy Muhammed Farhan

Hi Hassan

what are these things

[theRequest setValue:_clientName forHTTPHeaderField:@"X-Twitter-Client"];
[theRequest setValue:_clientVersion forHTTPHeaderField:@"X-Twitter-Client-Version"];
[theRequest setValue:_clientURL forHTTPHeaderField:@"X-Twitter-Client-URL"];

and

consumer:self.consumer

thanks

46 weeks 4 days ago
pramanathan1
@pramanathan1 pramanathan

MR.Foo & MR.Brian Ash i copy the above code and paste into the SA_OAuthtwitterengine. i got only error code " Error Domain=HTTP Code=401 "The operation couldn’t be completed. (HTTP error 401.)". may i know where this code implemented and invoked? please i request you to reply for this question.

1 year 3 weeks ago
chandaboy
@chandaboy Muhammed Farhan

Hi Hassan

what are these things

[theRequest setValue:_clientName forHTTPHeaderField:@"X-Twitter-Client"];
[theRequest setValue:_clientVersion forHTTPHeaderField:@"X-Twitter-Client-Version"];
[theRequest setValue:_clientURL forHTTPHeaderField:@"X-Twitter-Client-URL"];

and

consumer:self.consumer

thanks

46 weeks 4 days ago