I'm using the OAuthConsumer in my iOS application which makes use of the Tumblr API. Making API-Calls in general works fine. However, I struggle to upload any media. When all the parameters of my requests are ints or strings, I add them just like that:
[request setParameters:[NSArray arrayWithObjects:
[OARequestParameter requestParameterWithName:@"x_auth_username" value:username],
[OARequestParameter requestParameterWithName:@"x_auth_password" value:password],
nil]];
That obviously won't work for e.g. images.
I figured out that I probably will have to send this data as multipart/form-data
instead of application/x-www-form-urlencoded
and therefore, it won't have any effect on the oAuth signature. However, as far as I can tell, the OAuthConsumer only supports x-www-form-urlencoded
(with the relevant code lying in the NSMutableURLRequest+Parameters.m
). However, I'm not sure whether this is correct and, if so, I don't really know how to modify the Consumer
correctly. Any help would be appreciated!
Ok, I figured it out my self. There are several parts to this and since I saw other people having similar questions, I'll go into full length:
First of all, I was using an outdated version of OAuthConsumer. Instead of using the version that is linked on Google Code, you should use the more recent version from github since it includes the means to send a multipart form with more than strings in it.
Now, if I'm not completely wrong, what you should theoretically do now is the following:
//Setup the request...
[request setParameters:params];
[request attachFileWithName:@"data" filename:@"photo.jpg" contentType:@"image/jpeg" data:dataProp.data];
//Setup the fetcher and send the request...
This will generate an oAuth signature which includes only the oauth_...
-variables, putting all your other variables into the multipart form. This is how it should be and according to the documentation, you should be fine. Unfortunately, you aren't, tumblr will return a 401 error, resulting most likely from an invalid signature.
Here is what you really have to do:
//Setup the request...
[request setParameters:params];
[request prepare]; //Whaaaat?
[request attachFileWithName:@"data" filename:@"photo.jpg" contentType:@"image/jpeg" data:dataProp.data];
//Setup the fetcher, make sure "prepare" isn't called again, send the request...
This will work... Again, I'm pretty sure that this is not how oAuth is supposed to handle this but at least it works.
Tumblr's implementation of OAuth is pretty strange I'd say. I found why it is OK for authentication and blog request (see here). As I know, Tumblr works better with new OAuth library (this one). I my self uselessly spent some time trying to make all work on old OAuth for compatibility with ShareKit.
The solution I found suggest using ASIFormDataRequest and signing it with OAuth authentication information (originally found here). Yes, it looks like trying to crossbreed a hedgehog with a grass snake, but somehow it works for single images. But, after modifying this code, I couldn't upload multiple images.
Another solution is "TumblrUploadr", but it looks a bit too raw.