Upload PowerPoint via AFNetworking gets corrupt - objective-c

I receive a successfully response when uploading a PowerPoint via the below code. It does get upload but the file is corrupt. When opening the corrupt file on the server via PowerPoint I get this message:
"PowerPoint found a problem with content in filename.pptx. PowerPoint can attempt to repair the presentation."
- (void)updateDocument:(NSString *) path parameters:(FileUploadParameters*)para success:(void (^)(void))success failure:(void (^)(NSError *error))failure
{
_postData = nil;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:[ConfigurationUtil objectForKey:#"baseURL"]]];
_postData = [NSMutableData dataWithContentsOfFile:[path stringByStandardizingPath]];
_postData = [NSMutableData dataWithContentsOfFile:[path stringByStandardizingPath] options:NSDataReadingMapped error:nil];
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:HTTP_METHOD_POST
path:[self getQueryString:path parameter:para]
parameters:nil
constructingBodyWithBlock: ^(id <AFMultipartFormData>formData)
{
[formData appendPartWithFileData:_postData
name:[[path lastPathComponent] stringByDeletingPathExtension]
fileName:[[path lastPathComponent] stringByDeletingPathExtension] mimeType:#"application/powerpoint"];
}];
[request addValue:[NSString stringWithFormat:#"WRAP access_token=%#",[Tenant loadSharedTenantInstance].authToken] forHTTPHeaderField:#"Authorization"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
if (success)
success();
}
failure:^(AFHTTPRequestOperation* operation, NSError* error)
{
if (failure)
failure(error);
}
];
[operation start];
}

Your AFNetworking code looks fine. I don't think that's the culprit.
You can use the cmp command line tool to compare the two files (the original and the upload) byte-for-byte and see if there's a difference. I think there won't be.
More likely: it's a misleading error message, and it's actually a permissions issue on the computer with Powerpoint installed, as outlined in this Microsoft Knowledge Base article.

The below code corrects the problem. It appears that appendPartWithFileData was causing the issue. It changes the filesize and that seemed to register the file as corrupt.
_postData = nil;
_postData = [NSMutableData dataWithContentsOfFile:[path stringByStandardizingPath]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
NSString *queryString =[self getQueryString:path parameter:nil];
[request setURL:[NSURL URLWithString:queryString]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:_postData];
[request addValue:[NSString stringWithFormat:#"WRAP access_token=%#",[Tenant loadSharedTenantInstance].authToken] forHTTPHeaderField:#"Authorization"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
if (success)
success();
}
failure:^(AFHTTPRequestOperation* operation, NSError* error)
{
if (failure)
failure(error);
}
];
[operation start];

Related

AFNetworking 2 - Image upload - Request failed: unsupported media type (415)

I know this question was answered multiple times, but I tried all the answers with no luck. I don't think that I do something fundamentally wrong but something goes definitely wrong here.
I use the following code to upload PNG files to tinypng.com. As far as I can see the upload itself works, but I receive the error message: Request failed: unsupported media type (415)
The images I use are loaded as JPEG, then resized and transformed to PNG format. The saved files are fine. Now I want send them to the TinyPNG API before I save them to disc.
If anyone has an idea whats wrong or has experience with that service, please let me know.
Thanks in advance!
Detailed error message
Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: unsupported media type (415)"
UserInfo=0x6000000e4900 {
com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x600000220200> { URL: https://api.tinypng.com/shrink }
{
status code: 415, headers {
Connection = "keep-alive";
"Content-Length" = 77;
"Content-Type" = "application/json; charset=utf-8";
Date = "Tue, 16 Dec 2014 20:24:16 GMT";
Server = "Apache/2";
"Strict-Transport-Security" = "max-age=31536000";
"X-Powered-By" = "Voormedia (voormedia.com/jobs)";
}
},
NSErrorFailingURLKey=https://api.tinypng.com/shrink,
com.alamofire.serialization.response.error.data=<7b226572 726f7222 3a224261 64536967 6e617475
7265222c 226d6573 73616765 223a2244 6f657320 6e6f7420 61707065 61722074 6f206265 20612050
4e47206f 72204a50 45472066 696c6522 7d>,
NSLocalizedDescription=Request failed: unsupported media type (415)
}
The code I use
-(void) uploadImage:(NSImage *)image {
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:TINY_PNG_URL]];
CGImageRef cgRef = [image CGImageForProposedRect:NULL
context:nil
hints:nil];
NSBitmapImageRep *newRep = [[NSBitmapImageRep alloc] initWithCGImage:cgRef];
[newRep setSize:[image size]]; // if you want the same resolution
NSData *imageData = [newRep representationUsingType:NSPNGFileType properties:nil];
NSDictionary *parameters = #{#"username": USERNAME, #"password" : PASSWORD};
AFHTTPRequestOperation *operation = [manager POST:#"" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
//append image
[formData appendPartWithFileData:imageData
name:#"filename"
fileName:#"photo.png"
mimeType:#"image/png"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[operation start];
}
With the support of Mattijs from TinyPNG I've got it working! Thanks Mattijs!
The problem was, that the TinyPNG API expects the request body to only be the image data, which isn't the case with the multipart form data body I used in my original code.
My working solution is:
-(void) uploadImage:(NSImage *)image {
NSData *imageData = [self PNGRepresentationOfImage:image];
NSURL *url = [NSURL URLWithString:TINY_PNG_URL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:imageData];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"image/png" forHTTPHeaderField:#"Content-Type"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", USERNAME, PASSWORD];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id result) {
NSLog(#"Success: %# ***** %#", operation.responseString, result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[operation start];
}

expectFutureValue fails

Why I can't pass test? Any blocks of AFHTTPRequestOperation not called. Seems that expectFutureValue don't wait results and returns immediately. I trying on XCode 6.1 and Kiwi 2.3.1
Thanks!
context(#"AFNetworking", ^{
it(#"stubs a request with an error", ^{
NSError *error = [NSError errorWithDomain:#"com.luisobo.nocilla" code:123 userInfo:#{NSLocalizedDescriptionKey:#"Failing, failing... 1, 2, 3..."}];
stubRequest(#"POST", #"https://example.com/say-hello").
withHeaders(#{ #"X-MY-AWESOME-HEADER": #"sisisi", #"Content-Type": #"text/plain" }).
withBody(#"Adios!").
andFailWithError(error);
NSURL *url = [NSURL URLWithString:#"https://example.com/say-hello"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/plain" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"sisisi" forHTTPHeaderField:#"X-MY-AWESOME-HEADER"];
[request setHTTPBody:[#"Adios!" dataUsingEncoding:NSASCIIStringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
__block BOOL succeed = NO;
__block BOOL failed = NO;
__block NSError *capturedError = nil;
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
succeed = YES;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
capturedError = error;
failed = YES;
}];
[operation start];
[[expectFutureValue(theValue(failed)) shouldEventually] beYes];
});
});

AFNetworking JSON Request, neither success nor error block called

I'm trying to learn AFNetworking so have written a simple block. I'm trying to retrieve & log the json from the site url below.
NSString *string =
#"http://transportapi.com/v3/uk/bus/stop/490012745J/live.json?api_key=6ee115459cbeccdb902b14d39b61330d&app_id=9deefeb1&group=route";
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *mydict = (NSDictionary *)responseObject;
NSString *key;
for(key in mydict){
NSLog(#" key %#", key);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"ERROR");
}];
But neither the success or the failure block is being called. Can someone point out what I've done wrong?
You're not actually firing the operation you need to add
[[NSOperationQueue mainQueue] addOperation:operation];

ASIFormDataRequest uploads blank image

After searching here for a simple image upload with ASIFormDataRequest i finally got it working(sort of) but with a unexpected error.
My image is uploaded to my server but it is blank, 0 bytes in size.
Here is my code:
-(IBAction)uploadImage:(id)sender
{
NSData *data = UIImageJPEGRepresentation(self.imageView.image,0.6f);
NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:#"upload.png"];
[data writeToFile:file atomically:YES];
NSString *strURL = #"http://domain.com/upload.php";
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:strURL]];
UIImage *image1=[UIImage imageNamed:file];
NSData *imageData1=UIImageJPEGRepresentation(image1, 1.0);
[request setData:imageData1 withFileName:file andContentType:#"image/jpeg" forKey:#"avatar"];
[request setRequestMethod:#"POST"];
//[request appendPostData:body];
[request setDelegate:self];
[request setTimeOutSeconds:13.0];
request.shouldAttemptPersistentConnection = NO;
[request setDidFinishSelector:#selector(uploadRequestFinished:)];
[request setDidFailSelector:#selector(uploadRequestFailed:)];
[request startAsynchronous];
}
- (void)uploadRequestFinished:(ASIHTTPRequest *)request
{
NSLog(#" Error - Statistics file upload ok: \"%#\"",[request responseString]);
}
- (void)uploadRequestFailed:(ASIHTTPRequest *)request{
NSLog(#" Error - Statistics file upload failed: \"%#\"",[[request error] localizedDescription]);
}
My PHP code:
<?php
$target = "./";
$target = $target . basename( $_FILES['avatar']['name']) ;
$ok=1;
if(move_uploaded_file($_FILES['avatar']['tmp_name'], $target))
{
echo "The file ok";
}
else {
echo "Sorry, there was a problem uploading your file.";
}
?>
At first i thought it was a folder permision thing but i tested it with a simple html form upload(with the same php file,unedited) and the file was uploaded in full size.
I know that such a method of uploading a file is dangerous,but for the moment it is the only thing i got.
Any ideas why my file it's not getting uploaded?
Thanks.
Ok,i followed your advise and actually used AFNetwork
Here is my code for helping out others.
NSData *imageToUpload = UIImageJPEGRepresentation(_imageView.image, 0.5f);
AFHTTPClient *client= [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://domain.com"]];
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST" path:#"upload.php" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData: imageToUpload name:#"avatar" fileName:fullFilename mimeType:#"image/jpeg"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *response = [operation responseString];
NSLog(#"response: [%#]",response);
[MBProgressHUD hideHUDForView:self.view animated:YES];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if([operation.response statusCode] == 403){
NSLog(#"Upload Failed");
return;
}
NSLog(#"error: %#", [operation error]);
}];
[operation start];

AFNetworking POSTing malformed JSON - single quotes and [Object] refs

I am using AFNetworking and I am trying to POST a JSON structure. The problem is that instead of something like {"my_property":"my value"}, it's formatting it as {my_property:'my_value'}. I guess the loss of the first set of quotes is OK in most cases, but I'm not sure what to do with the non-JSON single quotes and am pretty confused as to why it would generate single quotes at all given that it knows it's creating JSON from an NSDictionary. Additionally, it's including [Object] refs where I would just expect a "{". This is what the server is getting:
...
num_matches: 32,
view_instance: properties_in_view: [Object],
[ { view_instance_ctr: 0, view_id: '4e5bb37258200ed9aa000011' },
...
The target is iOS 5.0, so I'm assuming it's using NSJSONSerialization to create JSON (although I haven't tried to verify this yet). The dictionary I send validates to JSON with isValidJSONObject. If I print out the serialized version, it looks great. The simplified version of the code looks like:
NSDictionary *params = myDictionaryThatValidatesToJSON;
httpClient.parameterEncoding = AFJSONParameterEncoding;
NSMutableURLRequest *request = [httpClient
requestWithMethod:#"POST" path:#"" parameters:params];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation start];
I'm hoping there's a bigDummy = NO flag I'm missing.
I think your issue is on the server side - ie. the debug you've quoted in your question is not the raw JSON text received by the server, but some reinterpretation of this that some component on the server has done.
Michael is correct. By using his code of data i'm using this to perform POST request with JSOn parameter :
// dataDictionary is your parameter dictionary
NSError *error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dataDictionary options:NSJSONWritingPrettyPrinted error:&error];
//NSString *jsonOut = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:webURL]];
[httpClient setParameterEncoding:AFFormURLParameterEncoding];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:#"Webservice URL"
parameters:nil];
NSMutableData *body = [NSMutableData data];
[body appendData:jsonData];
[request setHTTPBody:body];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"content-type"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// Print the response body in text
NSLog(#"Response: %#", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation start];