ASIFormDataRequest in AFNetworking? - objective-c

I have some code in ASIHTTP, but I want to move on AFNetworking.
I used ASIFormDataRequest for some POST requests and this code works fine:
NSURL *url = [NSURL URLWithString:#"http://someapiurl"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"123" forKey:#"phone_number"];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSLog(#"Response: %#", [[request responseString] objectFromJSONString]);
}
but, when I tried to do the same with AFNetworking, I got in problem with content-type (I guess).
This is AFNetworking code, and it doesn't work:
NSURL *url = [NSURL URLWithString:#"http://dev.url"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"123", #"phone_number",
nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"/api/get_archive" parameters:params];
[request setValue:#"application/x-www-form-urlencoded; charset=UTF8" forHTTPHeaderField:#"Content-Type"];
AFHTTPRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest
*request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Response: %#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
NSLog(#"Error: %#", error);
}];
[operation start];
URL is fine, this is checked.
I'm getting from server this:
{NSErrorFailingURLKey=http://dev.thisapiurl, NSLocalizedDescription=Expected content type {(
"text/json",
"application/json",
"text/javascript"
)}, got text/html}

The problem you're having is because you are instantiating an AFJSONRequestOperation, which by default expects a JSON-friendly response type. Are you expecting a JSON response? If not, you should use a less-specific Request class. For example, you could use HTTPRequestOperationWithRequest: .
NSURL *url = [NSURL URLWithString:#"http://dev.url"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"123", #"phone_number",
nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"/api/get_archive" parameters:params];
[request setValue:#"application/x-www-form-urlencoded; charset=UTF8" forHTTPHeaderField:#"Content-Type"];
//Notice the different method here!
AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
NSLog(#"Error: %#", error);
}];
//Enqueue it instead of just starting it.
[httpClient enqueueHTTPRequestOperation:operation];
If you have more specific request/response types (JSON, XML, etc), you can use those specific AFHTTPRequestOperation subclasses. Otherwise, just use the vanilla HTTP one.

I recently went through the same thing as you. Here is a custom class I wrote to handle pretty much any network request.
NetworkClient.h:
//
// NetworkClient.h
//
// Created by LJ Wilson on 3/8/12.
// Copyright (c) 2012 LJ Wilson. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString * const ACHAPIKey;
#interface NetworkClient : NSObject
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
block:(void (^)(id obj))block;
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
block:(void (^)(id obj))block;
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
alertUserOnFailure:(BOOL)alertUserOnFailure
block:(void (^)(id obj))block;
+(void)handleNetworkErrorWithError:(NSError *)error;
+(void)handleNoAccessWithReason:(NSString *)reason;
#end
NetworkClient.m:
//
// NetworkClient.m
//
// Created by LJ Wilson on 3/8/12.
// Copyright (c) 2012 LJ Wilson. All rights reserved.
//
#import "NetworkClient.h"
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"
#import "SBJson.h"
NSString * const APIKey = #"APIKeyIfYouSoDesire";
#implementation NetworkClient
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
block:(void (^)(id obj))block {
[self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
}
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
block:(void (^)(id obj))block {
if (syncRequest) {
[self processURLRequestWithURL:url andParams:params syncRequest:YES alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
} else {
[self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
}
}
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
alertUserOnFailure:(BOOL)alertUserOnFailure
block:(void (^)(id obj))block {
// Default url goes here, pass in a nil to use it
if (url == nil) {
url = #"MyDefaultURLGoesHere";
}
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:params];
[dict setValue:APIKey forKey:#"APIKey"];
NSDictionary *newParams = [[NSDictionary alloc] initWithDictionary:dict];
NSURL *requestURL;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:requestURL];
NSMutableURLRequest *theRequest = [httpClient requestWithMethod:#"POST" path:url parameters:newParams];
__block NSString *responseString = [NSString stringWithString:#""];
AFHTTPRequestOperation *_operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
__weak AFHTTPRequestOperation *operation = _operation;
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
responseString = [operation responseString];
id retObj = [responseString JSONValue];
// Check for invalid response (No Access)
if ([retObj isKindOfClass:[NSDictionary class]]) {
if ([[(NSDictionary *)retObj valueForKey:#"Message"] isEqualToString:#"No Access"]) {
block(nil);
[self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:#"Reason"]];
}
} else if ([retObj isKindOfClass:[NSArray class]]) {
NSDictionary *dict = [(NSArray *)retObj objectAtIndex:0];
if ([[dict valueForKey:#"Message"] isEqualToString:#"No Access"]) {
block(nil);
[self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:#"Reason"]];
}
}
block(retObj);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed with error = %#", [NSString stringWithFormat:#"[Error]:%#",error]);
block(nil);
if (alertUserOnFailure) {
[self handleNetworkErrorWithError:operation.error];
}
}];
[operation start];
if (syncRequest) {
// Only fires if Syncronous was passed in as YES. Default is NO
[operation waitUntilFinished];
}
}
+(void)handleNetworkErrorWithError:(NSError *)error {
NSString *errorString = [NSString stringWithFormat:#"[Error]:%#",error];
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:#"Connection Error"
message:errorString
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[myAlert show];
}
+(void)handleNoAccessWithReason:(NSString *)reason {
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:#"No Access"
message:reason
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[myAlert show];
}
#end
This adds in a couple of features you may not need or want, feel free to modify it as you need as long as the Copyright section stays in place. I use that APIKey to validate the request came from my app and not someone trying to hack things.
Calling it (assuming you have included NetworkClient.h:
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"ParamValue1", #"ParamName1",
#"ParamValue2", #"ParamName2",
nil];
[NetworkClient processURLRequestWithURL:nil andParams:params block:^(id obj) {
if ([obj isKindOfClass:[NSArray class]]) {
// Do whatever you want with the object. In this case, I knew I was expecting an Array, but it will return a Dictionary if that is what the web-service responds with.
}
}];
Also can:
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"ParamValue1", #"ParamName1",
nil];
NSString *urlString = #"https://SuppliedURLOverridesDefault";
[NetworkClient processURLRequestWithURL:urlString
andParams:params
syncRequest:YES
alertUserOnFailure:NO
block:^(id obj) {
if ([obj isKindOfClass:[NSArray class]]) {
// Do stuff
}
}];
So it will take in any number of parameters, inject an APIKey or anything else if you want and return back either a Dictionary or an Array depending on the web-service. This does expect SBJson BTW.

Related

asynchronous function doesn't return data

I wrote a function to fetch an NSDictionary from a URL.
[Data loadFromAPI:#"http://example.com/api" withSuccess:^(id data) {
NSMutableDictionary *result = (NSDictionary *)data;
CLS_LOG(#"result: %#", result);
} failure:^(NSError *error) {
CLS_LOG(#"Error: %#", error);
}];
The function it calls is the one below:
typedef void (^Success)(id data);
typedef void (^Failure)(NSError *error);
+ (void)loadFromAPI:(NSString *)apiURL withSuccess:(Success)success failure:(Failure)failure {
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:apiURL]];
NSMutableURLRequest *mutableRequest = [request mutableCopy];
request = [mutableRequest copy];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [JSONResponseSerializerWithData serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray *jsonArray = (NSArray *)responseObject ;
NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:
[self now], #"time",
jsonArray, #"response",
nil];
CLS_LOG(#"Result is: %#", result);
success(result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure?failure(error):nil;
}];
[operationQueue setMaxConcurrentOperationCount:1];
[operationQueue addOperations:#[operation] waitUntilFinished:NO];
}
Inside the function CLS_LOG(#"Result is: %#", result); returns the data returned. However, where I call the function CLS_LOG(#"result: %#", result); returns null. What am I doing wrong?
As it turns out [self now] returned null, so the NSDictionary wasn't being set properly.
The problem is
NSMutableDictionary *result = (NSDictionary *)data;
you cant directly do that, i wonder why you dont have a warning for that..
NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithDictionary:(NSDictionary *)data];
will probably solve the problem...

how to change my synchronous to asynchronous call in Objective-C?

hi friend i am beginner for objective-c.i have slow response from server side due to synchronous call. i analysed in google the call may be asynchronous means the response speed will be high, but i don't know much about NSURLConnection and GCD. so please help me how to change my call asynchronous . see my code below`
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString* oldToken = [self deviceToken];
NSString *newToken = [[[[deviceToken description]stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"My token is: %#", newToken);
[self setDeviceToken:newToken];
if (![newToken isEqualToString:oldToken])
{
[self calur:newToken];
}
}
- (NSString*)deviceToken{
return [[NSUserDefaults standardUserDefaults] stringForKey:#"deviceid"];
}
- (void)setDeviceToken:(NSString*)token{
[[NSUserDefaults standardUserDefaults] setObject:token forKey:#"deviceid"];
}
//This function used to store a notification device id to our notification databae
-(void)calur:(NSString *)device
{
NSString *post =[NSString stringWithFormat:#"deviceId=%#",device];
NSString *hostStr = #"https://myserver.com/Ver_2_0/notification/check.php?";
NSError *error = nil;
NSString *nocon=[NSString stringWithContentsOfURL:[NSURL URLWithString:hostStr]encoding:NSUTF8StringEncoding error:&error];
if (nocon == nil)
{
NSLog(#"NO Connection");
}
else
{
hostStr = [hostStr stringByAppendingString:post];
NSData *dataURL = [NSData dataWithContentsOfURL: [ NSURL URLWithString: hostStr ]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
NSLog(#"hostStr=%#",hostStr);
NSLog(#"serverOutput = %#",serverOutput);
NSLog(#"dataURL=%#",dataURL);
// NSData *dataurl=dataURL;
if([serverOutput isEqualToString:#"Token Updated Successfully"])
{
NSLog(#"badge updated");
}
else
{
NSLog(#"serverOutput = %#",serverOutput);
NSLog(#"not registered");
}
[serverOutput release];
}
}`
if (nocon == nil)
{
NSLog(#"NO Connection");
}
else
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
hostStr = [hostStr stringByAppendingString:post];
NSData *dataURL = [NSData dataWithContentsOfURL: [ NSURL URLWithString: hostStr ]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
NSLog(#"hostStr=%#",hostStr);
NSLog(#"serverOutput = %#",serverOutput);
NSLog(#"dataURL=%#",dataURL);
// NSData *dataurl=dataURL;
if([serverOutput isEqualToString:#"Token Updated Successfully"])
{
NSLog(#"badge updated");
}
else
{
NSLog(#"serverOutput = %#",serverOutput);
NSLog(#"not registered");
}
[serverOutput release];
});
}
a little snippet:
#import "AFNetworking.h"
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:self.value, #"POSTvar", nil];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL: [NSURL URLWithString:#"http://your.address"]];
NSURLRequest *request = [client requestWithMethod:#"POST" path:nil parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// do some with JSON
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
});
AFNetworking github

AFHTTPClient subclass with custom NSMutableURLRequest objects

My app is using AFNetworking for twitter API access and I've created a twitter api client by subclassing AFHTTPClient:
#import "AFHTTPClient.h"
#interface TwitterAPIClient : AFHTTPClient
+ (TwitterAPIClient *)sharedClient;
#end
#import "TwitterAPIClient.h"
#import "AFJSONRequestOperation.h"
static NSString * const kAFTwitterAPIBaseURLString = #"http://api.twitter.com/1/";
#implementation TwitterAPIClient
+ (TwitterAPIClient *)sharedClient {
static TwitterAPIClient *_sharedClient = nil;
static dispatch_once_t TwitterAPIClientToken;
dispatch_once(&TwitterAPIClientToken, ^{
_sharedClient = [[TwitterAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kAFTwitterAPIBaseURLString]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:#"Accept" value:#"application/json"];
return self;
}
#end
If I use getPath's & postPath's on the TwitterAPIClient, the API client returns JSON responses correctly, as I register a AFJSONRequestOperation as the operation class.
However, Sometimes, I need to create custom NSMutableURLRequest requests and not use the getPath's & postPath's AFHTTPClient functions.
When I use these requests, the response is getting back from the client is standard NSData and not NSDictionary as I get from AFJSONRequestOperation.
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1.1/account/verify_credentials.json"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.auth authorizeRequest:request];
AFHTTPRequestOperation* apiRequest = [[TwitterAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, NSDictionary* responseObject) {
[self createAccount];
self.account.username = [responseObject objectForKey:#"screen_name"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate didProfileLoaded:self.account];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (error!=nil) {
NSString* errorMessage = nil;
NSString* errorData = [error.userInfo objectForKey:NSLocalizedRecoverySuggestionErrorKey];
if (errorData!=nil) {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:[errorData dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
if (json!=nil && error==nil) {
NSArray* errorMeta = [json objectForKey:#"errors"];
if (errorMeta!=nil) {
errorMessage = [[errorMeta objectAtIndex:0] objectForKey:#"message"];
}
} else {
errorMessage = errorData;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate didUpdateFailed:errorMessage];
});
}
}];
[[TwitterAPIClient sharedClient] enqueueHTTPRequestOperation:apiRequest];
Is there a way I can force these AFHTTPRequestOperation to be created as AFJSONRequestOperation objects?
Just create an AFJSONRequestOperation directly, like so:
AFJSONRequestOperation* apiRequest = [[AFJSONRequestOperation alloc] initWithRequest:request];
[apiRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// ....
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// ...
}];
More examples here and here.

Asana API error - unsupported browser when using an ios client

I am sending an API call to Asana from an iOS client and am getting an HTML page with the title: Asana - Unsupported Browser which tells me something is wrong with the way I make the call.
My API calling code is as follows:
Client Settings are here:
- (id) initHTTPClient {
self = [super initWithBaseURL:[NSURL URLWithString:ASANA_BASE_URL]];
if (self) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:#"Accept" value:#"application/json"];
[self setParameterEncoding:AFJSONParameterEncoding];
[self setAuthorizationHeaderWithUsername:ASANA_API_KEY password:[NSString string]];
}
return self;
}
API call is constructed here:
- (void) getCurrentUser {
NSDictionary *parameters = [NSDictionary dictionary];
NSMutableURLRequest *request = [self requestWithMethod:#"GET" path:#"/users/me.json" parameters:parameters];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *error;
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error];
NSLog(#"Success, here's what we got: %#",response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure, error: %#",error.debugDescription);
}];
[operation start];
}

Upload Video to Vimeo in Objective C on iPhone

I am developing an app from which I want to upload Videos to Vimeo, Facebook and Youtube. Facebook and Youtube have pretty straightforward apis, Vimeo has a good developer documentation, but no Objective C framework. I have seen a couple of Apps which use Vimeo, so I was wondering if there is some kind of Framework out there I'm not aware of.
OK everybody. If you're still interested in how to upload a video to vimeo, here's the code. First you need to register an App with vimeo and obtain your secret and consumer key. Then you need to get the GTMOAuth framework from Google and possibly the SBJson framework. At the moment I unfortunately don't have the time to clean up the below code, but I thought this may be better than nothing for those, who need some help with vimeo. Essentially you authenticate with vimeo, get an upload ticket, upload the video with this ticket and then ad a title and some text.
The code below won't work out of the box, because there are a couple of view elements connected, but it should give you an understanding of what is happening.
#define VIMEO_SECRET #"1234567890"
#define VIMEO_CONSUMER_KEY #"1234567890"
#define VIMEO_BASE_URL #"http://vimeo.com/services/auth/"
#define VIMEO_REQUEST_TOKEN_URL #"http://vimeo.com/oauth/request_token"
#define VIMEO_AUTHORIZATION_URL #"http://vimeo.com/oauth/authorize?permission=write"
#define VIMEO_ACCESS_TOKEN_URL #"http://vimeo.com/oauth/access_token"
#import "MMVimeoUploaderVC.h"
#import "GTMOAuthAuthentication.h"
#import "GTMOAuthSignIn.h"
#import "GTMOAuthViewControllerTouch.h"
#import "JSON.h"
#interface MMVimeoUploaderVC ()
#property (retain) GTMOAuthAuthentication *signedAuth;
#property (retain) NSString *currentTicketID;
#property (retain) NSString *currentVideoID;
#property (assign) BOOL isUploading;
#property (retain) GTMHTTPFetcher *currentFetcher;
#end
#implementation MMVimeoUploaderVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
first = YES;
[GTMOAuthViewControllerTouch removeParamsFromKeychainForName:#"Vimeo"];
}
return self;
}
- (void)stopUpload {
if ( self.isUploading || self.currentFetcher ) {
[self.currentFetcher stopFetching];
}
}
- (void) setProgress:(float) progress {
// Connect to your views here
}
#pragma mark - handle error
- (void) handleErrorWithText:(NSString *) text {
//notify your views here
self.currentFetcher = nil;
self.isUploading = NO;
self.progressBar.alpha = 0;
self.uploadButton.alpha = 1;
}
#pragma mark - interface callbacks
//step one, authorize
- (void)startUpload {
if ( self.signedAuth ) {
//authentication present, start upload
} else {
//get vimeo authentication
NSURL *requestURL = [NSURL URLWithString:VIMEO_REQUEST_TOKEN_URL];
NSURL *accessURL = [NSURL URLWithString:VIMEO_ACCESS_TOKEN_URL];
NSURL *authorizeURL = [NSURL URLWithString:VIMEO_AUTHORIZATION_URL];
NSString *scope = #"";
GTMOAuthAuthentication *auth = [self vimeoAuth];
// set the callback URL to which the site should redirect, and for which
// the OAuth controller should look to determine when sign-in has
// finished or been canceled
//
// This URL does not need to be for an actual web page
[auth setCallback:#"http://www.....com/OAuthCallback"];
// Display the autentication view
GTMOAuthViewControllerTouch *viewController;
viewController = [[[GTMOAuthViewControllerTouch alloc] initWithScope:scope
language:nil
requestTokenURL:requestURL
authorizeTokenURL:authorizeURL
accessTokenURL:accessURL
authentication:auth
appServiceName:#"Vimeo"
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)] autorelease];
[[self navigationController] pushViewController:viewController
animated:YES];
}
}
//step two get upload ticket
- (void)viewController:(GTMOAuthViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuthAuthentication *)auth
error:(NSError *)error {
if (error != nil) {
[self handleErrorWithText:nil];
} else {
self.signedAuth = auth;
[self startUpload];
}
}
- (void) startUpload {
self.isUploading = YES;
NSURL *url = [NSURL URLWithString:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.upload.getQuota"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
- (void) myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *result = [info JSONValue];
//quota
int quota = [[result valueForKeyPath:#"user.upload_space.max"] intValue];
//get video file size
NSString *path;
path = #"local video path";
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *attrs = [manager attributesOfItemAtPath:path error: NULL];
UInt32 size = [attrs fileSize];
if ( size > quota ) {
[self handleErrorWithText:#"Your Vimeo account quota is exceeded."];
return;
}
//lets assume we have enough quota
NSURL *url = [NSURL URLWithString:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.upload.getTicket&upload_method=streaming"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher2:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
}
- (void) myFetcher2:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *result = [info JSONValue];
//fail here if neccessary TODO
NSString *urlString = [result valueForKeyPath:#"ticket.endpoint"];
self.currentTicketID = [result valueForKeyPath:#"ticket.id"];
if ( [self.currentTicketID length] == 0 || [urlString length] == 0) {
[self handleErrorWithText:nil];
return;
}
//get video file
// load the file data
NSString *path;
path = [MMMovieRenderer sharedRenderer].localVideoURL;
//get video file size
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *attrs = [manager attributesOfItemAtPath:path error: NULL];
UInt32 size = [attrs fileSize];
//insert endpoint here
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"PUT"];
[request setValue:[NSString stringWithFormat:#"%i", size] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"video/mp4" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[NSData dataWithContentsOfFile:path]];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
myFetcher.sentDataSelector = #selector(myFetcher:didSendBytes:totalBytesSent:totalBytesExpectedToSend:);
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher3:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
}
- (void)myFetcher:(GTMHTTPFetcher *)fetcher
didSendBytes:(NSInteger)bytesSent
totalBytesSent:(NSInteger)totalBytesSent
totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend {
NSLog(#"%i / %i", totalBytesSent, totalBytesExpectedToSend);
[self setProgress:(float)totalBytesSent / (float) totalBytesExpectedToSend];
self.uploadLabel.text = #"Uploading to Vimeo...";
}
- (void) myFetcher3:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
} else {
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
//finalize upload
NSString *requestString = [NSString stringWithFormat:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.upload.complete&ticket_id=%#&filename=%#", self.currentTicketID, #"movie.mov"];
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher4:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
}
- (void) myFetcher4:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
} else {
//finish upload
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *result = [info JSONValue];
self.currentVideoID = [result valueForKeyPath:#"ticket.video_id"];
if ( [self.currentVideoID length] == 0 ) {
[self handleErrorWithText:nil];
return;
}
//set title
NSString *title = [MMMovieSettingsManager sharedManager].movieTitle;
title = [title stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *requestString = [NSString stringWithFormat:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.setTitle&video_id=%#&title=%#", self.currentVideoID, title];
NSLog(#"%#", requestString);
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher5:finishedWithData:error:)];
}
}
- (void) myFetcher5:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
//set description
NSString *desc = #"Video created with ... iPhone App.";
desc = [desc stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *requestString = [NSString stringWithFormat:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.setDescription&video_id=%#&description=%#", self.currentVideoID, desc];
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher6:finishedWithData:error:)];
}
}
- (void) myFetcher6:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
//done
//alert your views that the upload has been completed
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self setProgress:0];
}
- (void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[GTMOAuthViewControllerTouch removeParamsFromKeychainForName:#"Vimeo"];
}
#pragma mark - oauth stuff
- (GTMOAuthAuthentication *)vimeoAuth {
NSString *myConsumerKey = VIMEO_CONSUMER_KEY; // pre-registered with service
NSString *myConsumerSecret = VIMEO_SECRET; // pre-assigned by service
GTMOAuthAuthentication *auth;
auth = [[[GTMOAuthAuthentication alloc] initWithSignatureMethod:kGTMOAuthSignatureMethodHMAC_SHA1
consumerKey:myConsumerKey
privateKey:myConsumerSecret] autorelease];
// setting the service name lets us inspect the auth object later to know
// what service it is for
auth.serviceProvider = #"Vimeo";
return auth;
}
#end
#import <Foundation/Foundation.h>
#protocol vimeodelagate;
#interface Vimeo_uploader : NSObject<NSURLSessionDelegate, NSURLSessionTaskDelegate>
#property(weak) id<vimeodelagate> delegate;
+(id)SharedManger;
-(void)pass_data_header:(NSData *)videoData;
- (void)Give_title_to_video:(NSString *)VIdeo_id With_name:(NSString *)name ;
#end
#protocol vimeodelagate <NSObject>
-(void)vimeouploader_succes:(NSString *)link methodName:(NSString *)methodName;
-(void)vimeouploader_progress:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalByte;
-(void)vimeouploader_error:(NSError *)error methodName:(NSString *)methodName;
#end
#define Aurtorizartion #"bearer 123456789" // replace 123456789 with your token, bearer text will be there
#define accept #"application/vnd.vimeo.*+json; version=3.2"
#import "Vimeo_uploader.h"
#implementation Vimeo_uploader
+(id)SharedManger{
static Vimeo_uploader *Vimeouploader = nil;
#synchronized (self) {
static dispatch_once_t oncetoken;
dispatch_once(&oncetoken, ^{
Vimeouploader = [[self alloc] init];
});
}
return Vimeouploader;
}
-(id)init{
if (self = [super init]) {
}
return self;
}
- (void)pass_data_header:(NSData *)videoData{
NSString *tmpUrl=[[NSString alloc]initWithFormat:#"https://api.vimeo.com/me/videos?type=streaming&redirect_url=&upgrade_to_1080=false"];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:tmpUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0];
[request setHTTPMethod:#"POST"];
[request setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[request setValue:accept forHTTPHeaderField:#"Accept"];//change this according to your need.
NSError *error;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &error];
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
if (!error) {
[self call_for_ticket:[json valueForKey:#"upload_link_secure"] complet_url:[json valueForKey:#"complete_uri"] videoData:videoData];
}else{
NSLog(#"RESPONSE--->%#",json);
}
}
- (void)call_for_ticket:(NSString *)upload_url complet_url:(NSString *)complet_uri videoData:(NSData *)videoData{
NSURLSessionConfiguration *configuration;
//configuration.timeoutIntervalForRequest = 5;
//configuration.timeoutIntervalForResource = 5;
configuration.HTTPMaximumConnectionsPerHost = 1;
configuration.allowsCellularAccess = YES;
// configuration.networkServiceType = NSURLNetworkServiceTypeBackground;
configuration.discretionary = NO;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:upload_url];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:#"PUT"];
[urlRequest setTimeoutInterval:0];
[urlRequest setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[urlRequest setValue:accept forHTTPHeaderField:#"Accept"];
NSError *error;
NSString *str_lenth = [NSString stringWithFormat:#"%lu",(unsigned long)videoData.length];
NSDictionary *dict = #{#"str_lenth":str_lenth,
#"Content-Type":#"video/mp4"};
NSData *postData12 = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
[urlRequest setHTTPBody:postData12];
// [urlRequest setHTTPBody:videoData];
// You could try use uploadTaskWithRequest fromData
NSURLSessionUploadTask *taskUpload = [session uploadTaskWithRequest:urlRequest fromData:videoData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (!error && httpResp.statusCode == 200) {
[self call_complete_uri:complet_uri];
} else {
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
NSLog(#"ERROR: %# AND HTTPREST ERROR : %ld", error, (long)httpResp.statusCode);
}
}];
[taskUpload resume];
}
-(void)call_complete_uri:(NSString *)complettion_url{
NSString *str_url =[NSString stringWithFormat:#"https://api.vimeo.com%#",complettion_url];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:str_url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0];
[request setHTTPMethod:#"DELETE"];
[request setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[request setValue:accept forHTTPHeaderField:#"Accept"];
//change this according to your need.
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
if ([httpResponse statusCode] == 201) {
NSDictionary *dict = [[NSDictionary alloc]initWithDictionary:[httpResponse allHeaderFields]];
if (dict) {
if([self.delegate respondsToSelector:#selector(vimeouploader_succes:methodName:)]){
// [self.delegate vimeouploader_succes:[dict valueForKey:#"Location"] methodName:#"vimeo"];
NSLog(#"sucesses");
NSString *str = [NSString stringWithFormat:#"title"];
[self Give_title_to_video:[dict valueForKey:#"Location"] With_name:str];
}else{
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
}
}
}else{
//9
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
NSLog(#"%#",error.localizedDescription);
}
}];
}
- (void)Give_title_to_video:(NSString *)VIdeo_id With_name:(NSString *)name {
NSString *tmpUrl=[[NSString alloc]initWithFormat:#"https://api.vimeo.com%#",VIdeo_id];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:tmpUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0];
[request setHTTPMethod:#"PATCH"];
[request setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[request setValue:accept forHTTPHeaderField:#"Accept"];//change this according to your need.
NSError *error;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &error];
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
NSString *str_description = #"description";
NSDictionary *dict = #{#"name":name,
#"description":str_description,
#"review_link":#"false"
};
NSData *postData12 = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
[request setHTTPBody:postData12];
if (!error) {
NSLog(#"RESPONSE--->%#",json);
[self.delegate vimeouploader_succes:[json valueForKey:#"link"] methodName:#"vimeo"];
}else{
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
//NSLog(#"%#",error.localizedDescription);
NSLog(#"Give_title_to_video_error--->%#",error);
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
NSLog(#"didSendBodyData: %lld, totalBytesSent: %lld, totalBytesExpectedToSend: %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
if([self.delegate respondsToSelector:#selector(vimeouploader_progress:totalBytesExpectedToSend:)]){
[self.delegate vimeouploader_progress:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend];}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if (error == nil) {
NSLog(#"Task: %# upload complete", task);
} else {
NSLog(#"Task: %# upload with error: %#", task, [error localizedDescription]);
}
}
#end
The vimeo-Api is enough. Take a closer look to the vimeo-upload-api
The interface can be used in any language which is able to send network-data. You have to create some NSURLConnections and you have to set the HTTP-Body like in their examples.
I wrote AFNetworking Client for Vimeo API - https://github.com/m1entus/RWMViemoClient