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
Related
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.
});
});
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.
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
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];
I am using AFNetworking and creating a post request for which I require json feedback. The code below works however I have two main questions; where do I release the ActivityIndicator Manager? The second question is this code correct, being new I get confused with blocks so I really want to know if I am doing it right thing for optimum performance, even though it works.
NSURL *url = [NSURL URLWithString:#"mysite/user/signup"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
AFNetworkActivityIndicatorManager * newactivity = [[AFNetworkActivityIndicatorManager alloc] init];
newactivity.enabled = YES;
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
usernamestring, #"login[username]",
emailstring, #"login[email]",
nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"mysite/user/signup"parameters:params];
[httpClient release];
AFJSONRequestOperation *operation = [AFJSONRequestOperation operationWithRequest:request success:^(id json) {
NSString *status = [json valueForKey:#"status"];
if ([status isEqualToString:#"success"]) {
[username resignFirstResponder];
[email resignFirstResponder];
[self.navigationController dismissModalViewControllerAnimated:NO];
}
else {
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:#"Login Unsuccessful"
message:#"Please try again"
delegate:NULL
cancelButtonTitle:#"OK"
otherButtonTitles:NULL];
[alert show];
[alert release];
}
}
failure:^(NSHTTPURLResponse *response, NSError *error) {
NSLog(#"%#", error);
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:#"Login Unsuccessful"
message:#"There was a problem connecting to the network!"
delegate:NULL
cancelButtonTitle:#"OK"
otherButtonTitles:NULL];
[alert show];
[alert release];
}];
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
[queue addOperation:operation];
NSLog(#"check");
}
Thank you very much for your help in advance :)
I know this question is a bit old, but I still wanted to contribute.
As steveOhh said, you should use [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES] to turn on the activity network indicator. It is a singleton, and hence it doesn't require you to manually alloc-init and release. As to the other question, I noticed you are missing some parameters in your block calls, also, you can do this, which is much cleaner code:
NSURL *url = [NSURL URLWithString:#"mysite/user/signup"];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:[NSURLRequest requestWithURL:url] success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// your success code here
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// your failure code here
}];
[operation start]; // start your operation directly, unless you really need to use a queue
Why not use this instead?
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
Hence there's no need to alloc and init
Can't say much on the other codes, just started out learning objective-C and AFNetworking.. :)
Regards,
Steve0hh