0

I currently upload images in the background to a server like this (the names get changed at the server to something better).

buildURL = [buildURL  stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *imageData = UIImageJPEGRepresentation(imageToUpload, 1.0);     //change Image to NSData

if (imageData != nil)
{
    NSString *filenames = [NSString stringWithFormat:@"imagename"];      //set name here
    NSLog(@"%@", filenames);
    NSString *urlString = buildURL;

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"POST"];

    NSString *boundary = @"---------------------------14737809831466499882746641449";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *body = [NSMutableData data];

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"filenames\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[filenames dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Disposition: form-data; name=\"userfile\"; filename=\".jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:imageData]];
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    // setting the body of the post to the reqeust
    [request setHTTPBody:body];
    // now lets make the connection to the web

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
            {

                NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                NSLog(@"Returned From Image Upload : %@",returnString);
            }];

}

This works fine, I can see the images finish in the background no problem. The thing is I want to change this to use NSURLSession and the delegate didSendBodyData so that I can monitor the upload.

I have found a load of information about the download but none really about upload. I have tried to do this with the request BUT the completion block NEVER happens.. I have also tried using uploadTaskWithStreamedRequest but I can not get the delegate to happen...

    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];

    NSURLSessionDataTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
                                          {
                                              NSLog(@"Image Uploaded ------------");
                                          }];

    [uploadTask resume];

I also found this StackOverflow 19985353 which seems to highlight some problems but I could really do with some example code. The image is picked from imagePicker if that helps.

I also tried both the answers here StackOverflow 19099448 but neither of them worked, again the block never executed. Is there something fundamental I am doing wrong with NSURLSession, a framework maybe! I also note I have no idea about the HTTP body which I have tried to play with but no luck.

Community
  • 1
  • 1
Recycled Steel
  • 2,272
  • 3
  • 30
  • 35
  • This might help you: [Tutorial](http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&ved=0CDcQFjAC&url=http%3A%2F%2Fwww.raywenderlich.com%2F51127%2Fnsurlsession-tutorial&ei=_IXzUqq3MJOMyAHhx4DwDA&usg=AFQjCNG8YRDnx7buLt1VGpFYqkoE91cXYg&bvm=bv.60799247,d.aWc) – 67cherries Feb 06 '14 at 12:55
  • @67cherries I went through this but still no joy. I have tried all examples but I simple can not get Delegates and/or Blocks to run. There are no errors either... – Recycled Steel Feb 06 '14 at 15:42
  • Are you using multithreading? – 67cherries Feb 06 '14 at 15:55
  • @67cherries For the most part no. There should be nothing going on in the background at this point. One thought does this work on iOS6? – Recycled Steel Feb 06 '14 at 16:24
  • @67cherries Nope does not work in iOS6, really no errors or warnings nothing........ – Recycled Steel Feb 06 '14 at 16:27

2 Answers2

1

Okay I did not realise that Session only works in iOS7 and above. To this end I have done a test and if iOS6 then I use NSURLConnection. The problem is I cannot get progress status from this (with the session I have an upload bar).

If anyone has any ideas about an upload progress bar using NSURLConnection then I would love to hear about it.

Recycled Steel
  • 2,272
  • 3
  • 30
  • 35
  • Apple docs talk about that [here](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html) under listing 2-3. – 67cherries Feb 06 '14 at 19:32
  • Sounds like you found your answer, and are asking another question. If so, you should accept this (your) answer, and start another SO question about updates during `NSURLConnection`. – Clay Bridges Feb 10 '14 at 21:32
-1
 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_urlToUpload];// create request
    [request setHTTPMethod:@"POST"];// request type
     [request setTimeoutInterval:60];
    [request setValue:@"application/octet-stream" forHTTPHeaderField: @"Content-Type"];// content type
  NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];// configuration
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];// session

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:file completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { }

Use the delegates


#pragma mark -
#pragma mark Session Upload Delegate Methods
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
    float status = (double)totalBytesSent / (double)totalBytesExpectedToSend;
    [[MTFileStreamer sharedFileStreamer] setCurrentStatus:status];
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}
Alex
  • 11,115
  • 12
  • 51
  • 64
  • can you please upload the necessary fields its very confusing for a beginner lets assume i have an api and key "image" what to do next ? – tryKuldeepTanwar Jul 28 '16 at 11:32