Uploading images to server - ios

I am trying to upload an image to a server (that is already built) and I am getting errors like Request has timed out. Other methods of sending text and fetch data from the server are working properly. However, sending an image I found it hard to do it.
I am using the following code at the moment:
-(void)uploadImage:(NSData*)image callbackBlock: (void (^)(BOOL success)) callbackBlock
{
NSString *path = [NSString stringWithFormat:#"upload"];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:image, #"image", nil];
[params addEntriesFromDictionary:self.sessionManager.authParameters];
NSMutableURLRequest *request = [self multipartFormRequestWithMethod:#"POST" path:path parameters:params constructingBodyWithBlock: ^(id <AFMultipartFormData>formData){
[formData appendPartWithFormData:image name:#"Image"];
}];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"!!!Response object: %#",responseObject);
callbackBlock(YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#",error.description);
callbackBlock(NO);
}];
[self enqueueHTTPRequestOperation:operation];
}
Do you have any idea what the problem is? Can you give me some suggestions or possible errors on the above code.
Thank you very much.

You can send your image as a base64 encoded text... This should work.
You can use this category to create base64 encoded image:
https://github.com/l4u/NSData-Base64

Related

AFNetworking get image if it is modified

I am using AFNetworking and download image if it is new image.
After I read though stackoverflow, currently, I am doing like this.
If the image is not modified, there will be cache in http header and I use that fact to check whether image is modified or not.
It is working well for most iOS. But, on iPhone 6s iOS 9.2.1, it always assume as new image.
How shall I detect whether image in server is modified already by using AFNetworking or may be NSUrlConnection?
- (void)downloadSplashScreenFromURL:(NSString *)urlStr
{
BOOL __block responseFromCache = YES; // yes by default
void (^requestSuccessBlock)(AFHTTPRequestOperation *operation, id responseObject) = ^(AFHTTPRequestOperation *operation, id responseObject) {
// response was returned from the server, not from cache
NSString *assestName = [urlStr lastPathComponent];
////WRITE TO FILEPATH
NSString *filePath = [splashDirectory() stringByAppendingString:
[NSString stringWithFormat:#"/%#", assestName]];
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
DLog(#"Splash : Splash image is empty");
NSData *pngData = UIImagePNGRepresentation(responseObject);
[pngData writeToFile:filePath atomically:YES];
return ;
}
if (responseFromCache) {
// response was returned from cache
DLog(#"SPLASH - RESPONSE FROM CACHE: %#", responseObject);
}
else {
DLog(#"SPLASH - NEW IMAGES FROM SERVER \n Response: %#", responseObject);
NSData *pngData = UIImagePNGRepresentation(responseObject);
[pngData writeToFile:filePath atomically:YES];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:USERDEFAULTS_SPLASH_SCREEN];
[[SplashHelper sharedInstance] showSplash:YES inWindow:[AppDelegate instance].window andSuccessBlock:^{
[[AppDelegate instance] startRunning];
}];
}
};
void (^requestFailureBlock)(AFHTTPRequestOperation *operation, NSError *error) = ^(AFHTTPRequestOperation *operation, NSError *error) {
NSInteger statusCode = operation.response.statusCode;
DLog(#"SPLASH - status code: %lu \nERROR: %#", (long)statusCode, [error localizedDescription]);
DLog(#"SPLASH - ERROR: %#", error);
};
DLog(#"Splash : CALL SPLASH SCREEN HELPER");
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation = [manager GET:urlStr
parameters:nil
success:requestSuccessBlock
failure:requestFailureBlock];
[manager.requestSerializer setTimeoutInterval:3.0f];
operation.responseSerializer = [AFImageResponseSerializer serializer];
[operation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
// this will be called whenever server returns status code 200, not 304
responseFromCache = NO;
DLog(#"Splash : cachedResponse = %#", cachedResponse);
return cachedResponse;
}];
}
I'm using #import "UIImageView+AFNetworking.h" category in my app to load an image from my server to app. Its working great, whenever an an update made for images on server, it'll generate new URLs, thus when I request with new URLs, AFNetworking will not find a cached image and will load new images from server.
And you should also check this, How do I get cached image stored by AFNetworking's UIImageView category? - there comes requirement when you needs to look after for an image inside your app's cache area.

Upload video chuck downloaded from one server to another server using AFNetworking

I am making an app that will transmit data from glasses to the server for broadcasting.
Til now i am able to download data from glasses to my iPhone document directory.
now i want to upload that downloaded data to my server so that we can broadcast that data to our users.
My iPhone and glasses are connected with each other with the help of WiFi, and i am trying to upload downloaded data via cellular network.
So basically my concept is that download data from glasses and upload that to server.
I have try to make my iPhone as a server to that my back end team could download data from my iPhone.
I got success in this method but the problem is that for this process the client and server should be on same private ip networks.
so now we have left with only one way that we download TS chucks from glasses and same time upload the TS file to our server for broadcasting.
I am using NFNetworking to download video chucks from glasses "TS File" but not able to upload that chucks to my server.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://xxx.xx.xx.x/abc/trunk/WebServices/app/webroot/xyz"]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request] ;
operation.outputStream = [NSOutputStream outputStreamWithURL:[NSURL URLWithString:#"http://abc.aa.a.a/xyz/trunk/WebServices/app/webroot/img/glasses/test/demo.ts"] append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// NSLog(#"Successfully downloaded file to %#", path);
// NSLog(#"download finished!");
if(_delegate && [_delegate respondsToSelector:#selector(ZBTM3U8SegmentDownloaderFinishDownload:)])
{
[_delegate ZBTM3U8SegmentDownloaderFinishDownload:self];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// NSLog(#"Error: %#", error);
}];
[operation start];
It goes in success state but data is not uploaded on server
server folder show empty.
- (void)postVideoOnServer {
NSDictionary *requestDict = #{ #"uniqueToken":#"101", #"user_id":#"102",};
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:_tsFileName];
NSData *selectedVideo = [NSData dataWithContentsOfFile:path];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation = [manager POST:#"http://xxx.x.x.xx/myi/public_html/WebServices/broad/axy" parameters:requestDict constructingBodyWithBlock: ^(id <AFMultipartFormData> formData) {
[formData appendPartWithFileData:selectedVideo name:#"file" fileName:#"filename.ts" mimeType:#"video/quicktime"];
} success: ^(AFHTTPRequestOperation *operation, id responseObject)
{
NSInteger statusCode = operation.response.statusCode;
NSLog(#"Status Code ::%d", statusCode);
NSLog(#"Response ::%#", responseObject);
[self handleVideoServiceResponse:responseObject];
}
failure : ^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %# %#", operation.responseString, error);
}];
[operation start];
}
it always return request time out error.
Thanks in advance.
Are you sure NSData *selectedVideo is not nil? i doubt you mime type too? Just a suggestion try use MIME: video/MP2T, it should fix your problem.

Jsonobject + Image Multipart AFNetworking

We are trying to send multi-part request to server using AFNetworking. We need to send one json object and two image files. Following is the curl request for same.
curl -X POST http://localhost:8080/Circle/restapi/offer/add -H "Content-Type: multipart/form-data" -F "offerDTO={"code": null,"name": "Merry X'Mas - 1","remark": "25% discount on every purchase","validityDate": "22-12-2014","domainCode": "DO - 1","merchantCode": "M-4","isApproved": false,"discountValue": 25,"discountType": "PERCENTAGE"};type=application/json" -F "image=#Team Page.png;type=image/png" -F "letterhead=#Team Page.png;type=image/png"
I know this should be fairly easy as I've implemented the server as well as android code for same. And my friend is working on iOS part of this. Also I searched a lot on google, but did not get anything useful. So, I know its against the rules of StackOverflow, but can you guys give me the code for same using AfNetworking? If not please redirect me to examples on same lines.
Edit:
Please find below code that we tried:
UIImage *imageToPost = [UIImage imageNamed:#"1.png"];
NSData *imageData = UIImageJPEGRepresentation(imageToPost, 1.0);
offerDTO = [[NSMutableDictionary alloc]init];
[offerDTO setObject(angry)"" forKey:#"code"];
[offerDTO setObject:[NSString stringWithFormat:#"Testing"] forKey:#"discountDiscription"];
[offerDTO setObject:[NSString stringWithFormat:#"Test"] forKey:#"remark"];
[offerDTO setObject:#"07-05-2015" forKey:#"validityDate"];
[offerDTO setObject:#"C-7" forKey:#"creatorCode"];
[offerDTO setObject:#"M-1" forKey:#"merchantCode"];
[offerDTO setObject:[NSNumber numberWithBool:true] forKey:#"isApproved"];
[offerDTO setObject:#"2.4" forKey:#"discountValue"];
[offerDTO setObject:[NSString stringWithFormat:#"FREE"] forKey:#"discountType"];
NSURL *urlsss = [NSURL URLWithString:#"http://serverurl:8180"];
AFHTTPClient *client= [AFHTTPClient clientWithBaseURL:urlsss];
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST"
path:#"/restapi/offer/add" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData)
{
NSData *myData = [NSJSONSerialization dataWithJSONObject:offerDTO
options:NSJSONWritingPrettyPrinted
error:NULL];
[formData appendPartWithFileData:imageData name:#"image"
fileName:#"image.jpg"
mimeType:#"image/jpeg"];
[formData appendPartWithFileData:imageData name:#"letterhead"
fileName:#"image.jpg"
mimeType:#"image/jpeg"];
[formData appendPartWithFormData:myData name:#"offerDTO"];
}
];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *jsons = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:nil];
}
failure:^(AFHTTPRequestOperation operation, NSError error)
{
NSLog(#"error: %#", [operation error]);
}
];
A couple of observations:
Your example is AFNetworking 1.x. AFNetworking 3.x rendition might look like:
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:#"1" withExtension:#"png"];
// If you need to build dictionary dynamically as in your question, that's fine,
// but sometimes array literals are more concise way if the structure of
// the dictionary is always the same.
// Also note that these keys do _not_ match what are present in the `curl`
// so please double check these keys (e.g. `discountDiscription` vs
// `discountDescription` vs `name`)!
NSDictionary *offerDTO = #{#"code" : #"",
#"discountDescription" : #"Testing",
#"remark" : #"Test",
#"validityDate" : #"07-05-2015",
#"creatorCode" : #"C-7",
#"merchantCode" : #"M-1",
#"isApproved" : #YES,
#"discountValue" : #2.4,
#"discountType" : #"FREE"};
// `AFHTTPSessionManager` is AFNetworking 3.x equivalent to `AFHTTPClient` in AFNetworking 1.x
NSURL *baseURL = [NSURL URLWithString:#"http://serverurl:8180"];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
// The `POST` method both creates and issues the request
[manager POST:#"/restapi/offer/add" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
NSError *error;
BOOL success;
success = [formData appendPartWithFileURL:fileURL
name:#"image"
fileName:#"image.jpg"
mimeType:#"image/png"
error:&error];
NSAssert(success, #"Failure adding file: %#", error);
success = [formData appendPartWithFileURL:fileURL
name:#"letterhead"
fileName:#"image.jpg"
mimeType:#"image/png"
error:&error];
NSAssert(success, #"Failure adding file: %#", error);
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:offerDTO options:0 error:&error];
NSAssert(jsonData, #"Failure building JSON: %#", error);
// You could just do:
//
// [formData appendPartWithFormData:jsonData name:#"offerDTO"];
//
// but I now notice that in your `curl`, you set the `Content-Type` for the
// part, so if you want to do that, you could do it like so:
NSDictionary *jsonHeaders = #{#"Content-Disposition" : #"form-data; name=\"offerDTO\"",
#"Content-Type" : #"application/json"};
[formData appendPartWithHeaders:jsonHeaders body:jsonData];
} progress:^(NSProgress * _Nonnull uploadProgress) {
// do whatever you want here
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(#"responseObject = %#", responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"error = %#", error);
}];
You are creating an operation here, but never add it to a queue to start it. I assume you do that elsewhere. It's worth noting that AFHTTPSessionManager doesn't support operations like the deprecated AFHTTPRequestOperationManager or AFHTTPClient used to. The above code just starts the operation automatically.
Note, AFNetworking now assumes the response will be JSON. Given that your code suggests the response is JSON, then note that no JSONObjectWithData is needed, as that's done for you already.
Right now your code is (a) creating UIImage; (b) converting it back to a NSData; and (c) adding that to the formData. That is inefficient for a number of reasons:
Specifically, by taking the image asset, loading it into a UIImage, and then using UIImageJPEGRepresentation, you may be making the resulting NSData considerably larger than the original asset. You might consider just grabbing the original asset, bypassing UIImage altogether, and sending that (obviously, if you're sending PNG, then change the mime-type, too).
The process of adding NSData to the request can result in larger memory footprint. Often if you supply a file name, it can keep the peak memory usage a bit lower.
you can pass your NSdictionary directly to manger post block in parametersfield
UIImage *imageToPost = [UIImage imageNamed:#"1.png"];
NSData *imageData = UIImageJPEGRepresentation(imageToPost, 1.0);
NSDictionary *offerDTO = #{#"code" : #"",
#"discountDescription" : #"Testing",
#"remark" : #"Test",
#"validityDate" : #"07-05-2015",
#"creatorCode" : #"C-7",
#"merchantCode" : #"M-1",
#"isApproved" : #YES,
#"discountValue" : #2.4,
#"discountType" : #"FREE"};
NSURL *baseURL = [NSURL URLWithString:#"http://serverurl:8180"];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
[manager POST:#"/restapi/offer/add" parameters:offerDTO constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:#"image"
fileName:#"image.jpg"
mimeType:#"image/jpeg"];
[formData appendPartWithFileData:imageData name:#"letterhead"
fileName:#"image.jpg"
mimeType:#"image/jpeg"];
[formData appendPartWithHeaders:jsonHeaders body:jsonData];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"responseObject = %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error = %#", error);
}]
;

AFNetworking returning NSCFData; issue with registerHTTPOperationClass [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am new to AFNetworking and am making a call to a simple login api that returns json like:
{"status":"success","data":{"auth_token":"12jt34"}}
I'm doing it via the following but it is returning __NSCFData rather than something that I can manipuate.
NSURL *baseURL = [NSURL URLWithString:#"http://localhost:3000/arc/v1/api/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
uname,#"email", pwd, #"password",
nil];
[httpClient postPath:#"login-mobile" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *className = NSStringFromClass([responseObject class]);
NSLog(#"val: %#",className);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
and it outputs:
2013-03-21 14:52:51.290 FbTabbed[21505:11303] val: __NSCFData
but I'd like it for it to be a dictionary that I can manipulate which is how I think it is supposed to work? What am I doing wrong?
[httpClient defaultValueForHeader:#"Accept"];
should be:
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
Yes, responseObject is a NSData. You can then parse it into a dictionary or array using NSJSONSerialization method JSONObjectWithData:
NSURL *baseURL = [NSURL URLWithString:#"http://localhost:3000/arc/v1/api/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
uname,#"email", pwd, #"password",
nil];
[httpClient postPath:#"login-mobile" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSAssert([responseObject isKindOfClass:[NSData class]], #"responseObject is supposed to be a NSData"); // it should be a NSData class
NSError *error;
self.results = [NSJSONSerialization JSONObjectWithData:responseObject
options:0
error:&error];
if (error != nil)
{
// handle the error
// an example of the sort of error that could result in a parse error
// is if common issue is that certain server errors can result in an
// HTML error page (e.g. you have the URL wrong, your server will
// deliver a HTML 404 page not found page). If you want to look at the
// contents of the `responseObject`, you would:
//
// NSLog(#"responseObject=%#", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
}
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
Obviously, your results object would be a NSDictionary or NSArray, depending upon the type of response you get from your API.
What am I doing wrong?
NSStringFromClass() returns the name of the class you pass in as an NSString object.
If you want to make a dictionary out of the returned JSON string, then you have to parse it, for example using the NSJSONSerialization class.

issue With AFNetworking?

I Wanna Get Data From PhP Page
My Code Is
NSURL *url = [NSURL URLWithString:#"http://avicenna-apps.com/harleychatget.php"];
AFHTTPClient * Client = [AFHTTPClient clientWithBaseURL:url];
[Client defaultValueForHeader:#"Accept"];
[Client getPath:#"" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Data %#",responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
The Output Is
Data <32352020 32303133 2d30312d 31302030 383a3234 3a353620 2041686d 65642020 68656c6c 6f206865 6c6c6f20 3c627220 2f3e3234 20203230 31332d30 312d3130 2030383a 32343a35 30202041 686d6564 20203c62 72202f3e 32332020 32303133 2d30312d 31302030 383a3234 3a343920 2041686d 65642020 3c627220 2f3e3230 20203230 31332d30 312d3130 2030383a 32343a34 38202041 686d6564 20203c62 72202f3e 32312020 32303133 2d30312d 31302030 383a3234 3a343820 2041686d 65642020 3c627220 2f3e200a 0a>
Any Help Please ?
That is binary data. You should convert it.
Try NSString *response = [[NSString alloc] initWithData:(NSData*)responseObject encoding:NSUTF8StringEncoding]; to get the response as string
or simple:
NSString *response = request.responseString;

Resources