iOS: How to use operation queues to download large amount of data? - ios

I am developing an iOS application in which I have to download large data like images and videos locally on device. The data can be in GB's and there can be thousands of files to download. So, whats the best way to tackle this situation. Because it can have many failures like request time out etc.
Also I have to updated core data that if the file has been successfully downloaded or not.
Any best and simple way would be appreciated.

Try taking a look at AFNetworking framework, handles almost everything for you and probably faster then you could implement.
Also do the downloading on a background thread using GCD. I've had decent results downloading 50Mb files.

You can use AFNetworking for that. it is a best API for dealing with web services now a days .you can download Latest AFNetworking API for iOS from github and.
you can use
- (void)uploadImageAtUrl:(NSURL*)url
{
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:#"yourImg.jpg"], 0.5);
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:imageData name:#"yourImg" fileName:#"yourImg.jpg" mimeType:#"image/jpeg"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
//Check progress
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[httpClient enqueueHTTPRequestOperation:operation];
}

Related

Download folder using AFNetworking in ios

I would like to download a folder which consists several kind of files(png,jpg,mov,txt and pdf). I am using AFNetworking. I have used below code for downloading,
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[Utilities urlencode:imageURL]]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:str_path append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
//NSLog(#"Successfully downloaded file to %#", str_path);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %# =====%# =======%#", error.localizedDescription,str_path,imageURL);
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToRead)
{
float progress = totalBytesWritten / (float)totalBytesExpectedToRead;
NSLog(#"Download Percentage: %f %%", progress*100);
}];
[operation start];
The above code works fine for individual files. But i have got error code of 21 while downloading folder. Any help would be greatly appreciated.
HTTP does not support downloading multiple files in one request. This is pretty much the same question asked here in reverse.
If you have FTP access you can use the CFFTP API to download the contents of a directory.

Downloading images and videos from WCF service IOS

I am new to web services and I have searched it but I couldn't find any documents about it. Is there any way to download images and videos from WCF Service and save the my app's document files? or do I need to use different way for download?
Thanks for your advice and interest.
Try using AFNetWorking: https://github.com/AFNetworking/AFNetworking
This is a sample how I download files from a WCF:
NSMutableURLRequest *reqeust = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:{url}]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:reqeust];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:{path_on_disk} append:NO];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
//Download progress
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Download failed
}];
[operation start]

Download multiple files in queue with AFDownloadRequestOperation

I'm using AFDownloadRequestOperation + AFNetworking to download and resume a list of files from a server. The code is working great at downloading and resuming multiple files at a time. But how to queue all operations inside an operations queue and execute the operation one by one?
Here's my current code
// request the video file from server
NSString *downloadURL = [NSString stringWithFormat:#"%#%#", [recipe download_url], [step valueForKey:#"video"]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:downloadURL]];
AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:videoFile shouldResume:YES];
// done saving!
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Done downloading %#", videoFile);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %ld", (long)[error code]);
}];
// set the progress
[operation setProgressiveDownloadProgressBlock:^(AFDownloadRequestOperation *operation, NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) {
float progress = ((float)totalBytesReadForFile) / totalBytesExpectedToReadForFile;
[progressBar setProgress:progress];
}];
[operation start];
You'll either need to add the operations to AFHTTPClient's operationQueue, or add them to a NSOperationQueue you've made yourself.
Then set the number of maximum concurrent operations for the queue your using to 1
Change
[operation start];
to
[[YourAFHTTPClientSubclass sharedInstance] enqueueHTTPRequestOperation:operation];
By default, this will have a maximum number of operations "determined dynamically by the NSOperationQueue object based on current system conditions".
If you really want to force everything to one at a time, do:
[YourAFHTTPClientSubclass sharedInstance].operationQueue.maxConcurrentOperationCount = 1;
This will block all network operations until the operation is finished.
Of course, you can make your own operation queue as Audun suggested, but it's probably better to let the system decide what to do based on current conditions.
Depending on your use case, you may want to set the priority of the operations of the video downloads to low:
operation.queuePriority = NSOperationQueuePriorityLow
This will allow other network operations to be placed in the queue at a higher priority than your video downloads.

Sending Images and data to PHP server-side

It,s my first time trying to send Images & Data to a PHP Server from an app, and I am quite confused as to what's the best way to achieve this.
In my research, I came across AFNetworking library and this base64 library (which I would take suggestion in another one), but I don't know if I can achieve what I want with that or how to implement it.
What I want to do is to send data & images that have a relationship.
Lets say the User has to upload their user details + their picture and their house details + a picture
my JSON would be something like
{
"userDetails": { "name":"jon",
"surname":"smith",
"phone":"123412",
"userPic":"base64pic"
},
"house": { "address":"123 asd",
"postcode":"w2 e23",
"housePic":"base64pic"
}
}
of course that JSON would also have to include security validations.
My problem comes when I would like to avoid using base64 encoding given the 33% size increase and I don't know how I could send the same information to PHP.
I get very confused when trying to send images & data that have a relationship and should be stored taking that relationship into account in the server.
Basically What I am looking for is a way to send the same information but not base64 encoded images but keeping the relationship in the data and trying to send as fewer request as possible. Is it possible? if so How?
look at this example for instance, eveything is pretty self explanatory but ask me if you have any questions
-(void) postStuff{
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"https://www.yourdomain.com/"]];
NSDictionary *parameter = #{#"body"#"Anything you want to say!"};
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"api/v1/posts/newpost/" parameters:parameter constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:imageData name:#"image" fileName:#"image.png" mimeType:#"image/png"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLOG(#"DONE!!!");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLOG(#"Error: %#", error);
}];
[httpClient enqueueHTTPRequestOperation:operation];
}

iOS - "Upload progress view" like the new facebook app

I would like to have an "Upload-progress-view", in my app. Just like the one the new Facebook app has. The "Upload view" is only visible if an upload-progress is active.
The UIView shoud be visible on every UIViewController in my app.
Can I insert the "Upload-progress-view" in my AppDelegate?
I'am using AFNetworking.
/ Morten
Screenshot:
As you can see it is a simpel UIView with a UIProgressView in it. My problem is how do I show this progress-view on every views (different UIViewControllers)?
This progressBar can do the same behaviour.
Are you using ASIHttpRequest to do the upload?
If yes take a look at Cocoa File Upload with Progress Bar
EDITED:
Ok, so use this
NSURL *url = [NSURL URLWithString:#"http://api-base-url.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:#"avatar.jpg"], 0.5);
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/upload" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:imageData name:#"avatar" fileName:#"avatar.jpg" mimeType:#"image/jpeg"];
}];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
[operation setUploadProgressBlock:^(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];
from GitHub AFNetworking - File Upload with Progress Callback

Resources