1

I have a need to upload a file to our server. However the server will process the file and fire it into a database. I am looking at NSInputStream which appears to work fine, however, I also need additional parameters like user token and file extension and I am not sure how to achieve this. I can use HTTPBodyStream for the stream itself, but then the method complains that not all parameters are supplied. The code I am using is below and is based on other areas where I post data to the web method.

- (IBAction)uploadFile:(id)sender {

// File will be replaced in production with selected file from resources directory
NSString* path = [[NSBundle mainBundle] pathForResource:@"myFile"
                                                 ofType:@"docx"];

NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:path];

// JSON Method
NSURL *uploadURL = [NSURL URLWithString:@"myDomain/myMethod"]; 

NSDictionary *requestDict = [[NSDictionary alloc] initWithObjectsAndKeys:
                           @"userTokenValue", @"userToken",
                           stream,@"fileStream",
                           @"docx", @"fileExt",
                           nil];

NSError *error;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:requestDict options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:&error];

NSString *json=[[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];

NSData *postData=[NSData dataWithBytes:[json UTF8String] length:[json length]];

request = [[NSMutableURLRequest alloc] initWithURL:uploadURL];

// Allows all parameters to be sent in other calls in the app, however generates SIGABRT here - detail below
[request setHTTPBody:postData];

// Reaches method, but method complains that not all parameters are supplied obviously
[request setHTTPBodyStream:stream];

[request setHTTPMethod:@"POST"];

NSError *requestError=nil;
NSURLResponse *response = nil;
NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&requestError];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
if (requestError == nil) {
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
        if (statusCode != 200) {
            NSLog(@"Warning, status code of response was not 200, it was %ld", (long)statusCode);
        }
    }

    NSError *error;
    NSDictionary *returnDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
    if (returnDictionary) {
        NSLog(@"returnDictionary=%@", returnDictionary);
    } else {
        NSLog(@"error parsing JSON response: %@", error);

        NSString *returnString = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
        NSLog(@"returnString: %@", returnString);
    }
} else {
    NSLog(@"NSURLConnection sendSynchronousRequest error: %@", requestError);
}

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

The SIGABRT mentioned above is:

'NSInvalidArgumentException', reason: 'Invalid type in JSON write (__NSCFInputStream)'

How can I stream the file data via the web method as well as supplying the other parameters. Thanks.

Borys Verebskyi
  • 4,160
  • 6
  • 28
  • 42
Tony Law
  • 293
  • 2
  • 13
  • Why using `NSStream` exactly? In JSON, you can only put `NSArray`, `NSDictionary`, `NSString`, `NSNumber` objects (NSNull also I think). But not `NSStream` objects. So that explains your issue. Note also in `setHTTPBodyStream:` doc: "Setting a body stream clears any data in HTTPBody. These values are mutually exclusive." – Larme Mar 24 '16 at 13:24
  • Sorry, should have explained better. I am only using one of HTTPBody or HTTPBodyStream. Not both at the same time, I put it in to show I had tried both. – Tony Law Mar 24 '16 at 13:26
  • Honestly, I'm trying NSInputStream as this is the first time I have had to upload a file and after some digging, this seems the way to do it. I'm just not sure how to get the other parameters in. – Tony Law Mar 24 '16 at 13:28
  • Did you ever get this working? – John Riselvato Sep 07 '16 at 15:32

0 Answers0