iOS 5 - AFNetworking - Uploading Video - iphone

For my app, users will be able to record a video or choose a video from their photo album and through a php script upload the video file to the server. To upload the file to the server, I am using AFNetworking. I originally tried to upload the video from the photo album, but since I could not get that to work I added a video (that I know uploads fine through an html front I made for the php script) into the main bundle.
The code is:
NSString *vidURL = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"mov"];
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:vidURL]];
NSLog(#"The test vid's url is %#.",vidURL);
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL fileURLWithPath: #"http://www.mywebsite.com"]];
NSMutableURLRequest *afRequest = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/upload.php" parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData)
{
[formData appendPartWithFileData:videoData name:#"file" fileName:#"test.mov" mimeType:#"video/quicktime"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest];
[operation setUploadProgressBlock:^(NSInteger bytesWritten,long long totalBytesWritten,long long totalBytesExpectedToWrite)
{
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];
My PHP script runs fine as I am able to upload the same video via an HTML form. The above code fails to get to the setUploadProgressBlock, however.
Does anything stick out as broken to anyone or is there something else I am missing?
Thanks in advance

This is what I used to fix the problem:
httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://www.mysite.com"]];
NSMutableURLRequest *afRequest = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/upload.php" parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData)
{
[formData appendPartWithFileData:videoData name:#"file" fileName:#"filename.mov" mimeType:#"video/quicktime"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest];
[operation setUploadProgressBlock:^(NSInteger bytesWritten,long long totalBytesWritten,long long totalBytesExpectedToWrite)
{
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {NSLog(#"Success");}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {NSLog(#"error: %#", operation.responseString);}];
[operation start];

Maybe the objects are getting deallocated immediately. Make the AFHTTPClient an instance variable of your class or subclass it and make it a singleton.
More Important: Replace this line:
[operation start];
with:
[httpClient enqueueHTTPRequestOperation:operation];

Related

How to avoid delay of webservice(ASIHTTPRequest) response in iPhone?

In my iPhone app handling web service for storing and retrieving data.Now i am using the following code for web service handling.
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"1" forKey:#"id"];
[request setTag:100];
[request setDelegate:self];
[request startAsynchronous];
By this code i got response in 'requestFinished' method.My problem is web service response is very delay(depends upon internet speed).How to make response from web service very fast?Please help me.
I think you want to send json objects by post method..delay is depend on your server(how fast it handle request and response back) but i suggest you to use progress bar and blocks to handle network request..
loadingHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
loadingHUD.labelText = NSLocalizedString(#"Downloading", nil);
loadingHUD.mode=MBProgressHUDModeAnnularDeterminate;
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) lastObject];
// Add your filename to the directory to create your saved file location
NSString* destPath = [documentDirectory stringByAppendingPathComponent:[fileName stringByAppendingString:#".mov"]];
NSURL *url = [NSURL URLWithString:mainURL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:postURL parameters:postRequest];
NSLog(#"postRequest: %#", postRequest);
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:destPath append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Successfully downloaded file to %#",[[NSString alloc] initWithData:operation.responseData encoding:NSASCIIStringEncoding]);
// Give alert that downloading successful.
NSLog(#"Successfully downloaded file to %#", destPath);
NSLog(#"response: %#", operation.responseString); // Give alert that downloading successful.
// [self.target parserDidDownloadItem:destPath];
loadingHUD.detailsLabelText = [NSString stringWithFormat:#"%# %i%%",#"Downloading",100];
[loadingHUD hide:TRUE];
[DBHelper savePurchaseId:fileName];
[self movieReceived];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
// Give alert that downloading failed
NSLog(#"Error: %#", error);
// [self.target parserDidFailToDownloadItem:error];
[loadingHUD hide:TRUE];
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite)
{
// Progress
progress = ((float)totalBytesWritten) / fileSize;
loadingHUD.progress = progress;
}];
[operation start];
}
We cant control the internet speed due to the different network provider or environment when the client is using your app.
But you can put your web-services to run in background without effecting your main function.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code for webservices calling
dispatch_async(dispatch_get_main_queue(), ^{
//functions after your webservices done, for example reload the table or hide the loading bar.
});
});

AFHTTPClient does not send complete data

I am sending a wav file using the following code, however, the process stops at
Sent 131072 of 141359 bytes
So? Is there some problem with the code? Or am i missing something?
NSString *vidURL = [[NSBundle mainBundle] pathForResource:#"M1F1-int24WE-AFsp" ofType:#"wav"];
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:vidURL]];
NSURL *url = [NSURL URLWithString:#"http://apps2.mobiiworld.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
// NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:#"Romantic.jpg"], 0.5);
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/staging/krafttesting/upload.php" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:videoData name:#"file" fileName:#"recording.wav" mimeType:#"audio/vnd.wave"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
// [httpClient enqueueHTTPRequestOperation:operation];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {NSLog(#"Success");}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", operation.responseString);
NSLog(#"error: %#", error.userInfo);
}];
[operation start];
I got the solution. It seems AFHTTPClient works only when ARC is on. I had ARC off, due to which it was not working - Though i had no errors received.

AFNetworking with AFJSONRequestOperation and filedata never completes

I'm using AFNetworking to post json data to my webservice and get a json response back. However now I also want to add multipart formdata to these POST's. If I do this (even without the parameters I added first) the completion block never fires. The progress block DOES fire and I can see that the file uploads correctly.
Does anybody have any experience posting images like this with AFNetworking? I am using the latest AFNetworking source / version.
This is my initial code for posting a dictionary with json in it. This works fine.
NSMutableDictionary *postdata = [[NSMutableDictionary alloc] init];
[postdata setObject:[postdictionary JSONString] forKey:#"request"];
NSMutableURLRequest *jsonRequest = [httpClient requestWithMethod:#"POST"
path:path
parameters:postdata];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:jsonRequest success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {// Success} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {// Failure }];
[operation start];
This is the version of the code for submitting an image (doesn't work)
NSMutableURLRequest *jsonRequest jsonRequest = [httpClient multipartFormRequestWithMethod:#"POST" path:path parameters:postdata constructingBodyWithBlock: ^(id <AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:#"photo" fileName:#"photo.jpg" mimeType:#"image/jpeg"];
[formData throttleBandwidthWithPacketSize:5000 delay:0.1];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:jsonRequest];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Upload succes");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Upload failed");
}];
[operation start];
I use this code on a number of apps and havent had any problems with it (note I am using the AFJSONRequestOperation and AFRestClient)
set the request
// I have a shared singleton in a separate file APIClient.h
AFRESTClient *httpClient = [APIClient sharedClient];
NSURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:method parameters:params constructingBodyWithBlock: ^(id <AFMultipartFormData> formData)
{[formData appendPartWithFileData:imageData
name:#"image"
fileName:#"image.png"
mimeType:#"image/png"];
}];
then the operation,
AFJSONRequestOperation *operation = [[AFJSONRequestOperation alloc] initWithRequest:request];
my progress block
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
CGFloat progress = ((CGFloat)totalBytesWritten) / totalBytesExpectedToWrite * 100;
[SVProgressHUD showProgress:50 status:[NSString stringWithFormat:#"%0.1f %%", progress]];
}];
success block (my API returns a stat -ok or fail, then the data (same as flickr API)
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id response) {
NSLog(#"response string: %#", operation.responseString);
NSString *resultStat = [response objectForKey:#"stat"];
if ([resultStat isEqualToString:#"ok"]) {
//success
// do something with your data that is returned from the API
} else {
//error
NSLog(#"Data Error: %#", response);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error localizedDescription]);
}];
[httpClient enqueueHTTPRequestOperation:operation];
cannot see any issues with your code, few possibilities:
try setting short timeout interval and check if request completes
[request setTimeoutInterval:5];
also try commenting out the throttling line and see if it changes anything

AFHTTPRequestOperation doesn't work after stand by mode

I am developing a app which upload multiple files.
For uploading, I use AFHTTPRequestOperation. It successfully works, But If I lock and after it unlock the screen,then It stop uploading files.
My code for upload file is here
NSUserDefaults *defaultUser = [NSUserDefaults standardUserDefaults];
NSString *userId = [defaultUser stringForKey:#"UserId"];
AFHTTPClient *client= [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",UploadURL,userId]]];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:nil];
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST" path:nil parameters:params constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData: data name:#"f" fileName:[NSString stringWithFormat:#"%d_image.jpeg",rand()] mimeType:#"image/jpeg"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", [operation error]);
if(error.code == -1001){
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"The request timed out." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[myAlert show];
}
}];
[operation start];
Can anyone give me suggestion for handle this situation.
Thanks.
(1) Add this code:
[operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
// Handle iOS shutting you down (possibly make a note of where you
// stopped so you can resume later)
}];
(2) Change this line:
[operation start];
to
[client enqueueHTTPRequestOperation:operation];
(3) Keep a strong reference to your AFHTTPClient (this is typically done for AFHTTPClient with the singleton pattern) so that your operations don't get deallocated

AFNetworking setImageWithURLRequest download progress

I am using this code to set image to UIImageView.
NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:imageToLoad]];
[imageView setImageWithURLRequest:URLRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[cell.image setImage:image];
[cell.activityIndicator stopAnimating];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
// Nothing
}];
But I want to track download progress with that method, is it possbile to do it in setImageWithURLRequest method?
Normally I do this to show loading progress percentage:
[SVProgressHUD showWithStatus:#"Start download..."];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:link]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// success
[SVProgressHUD showSuccessWithStatus:#"Done."];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// failed
[SVProgressHUD showErrorWithStatus:#"Failed."];
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
[SVProgressHUD showWithStatus:[NSString stringWithFormat:#"Downloading... %0.0f%%", totalBytesRead*100*1.0/(totalBytesRead+totalBytesExpectedToRead)]];
}];
Out of the box, no UIImageView+AFNetworking category doesn't have this functionality. However, it can easily be added to by adding this method to the category:
-(void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block{
[self.af_imageRequestOperation setDownloadProgressBlock:block];
}
Take a look at this cocoa pod: https://github.com/xmartlabs/XLRemoteImageView . It uses objective-c internals to achieve what you want. I hope it helps you.