objective-ciossocketsaudio-streamingcfstream

Upload audio - http streaming


I'm trying to upload a linear file under http in streaming mode. The idea is do this steps simultaneously, 1) Thread 1: record an audio file and store it in a temp file 2) Thread 2: Take n bytes from temp file and send it to an http server.

How can I write an http stream?, On CFHTTPStream I did not see write methods, only read :s Do I need use sockets? Thanks!!!

My actual code is

   CFWriteStreamRef stream;
   NSString *strUrl = @"myurl";       
   NSURL *url = [[[NSURL alloc] initWithString:strUrl] retain];

   CFStringRef requestMethod = CFSTR("GET");

   CFHTTPMessageRef message= CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, (CFURLRef)url, kCFHTTPVersion1_1);

    CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Content-Type"),
                                     CFSTR("multipart/form-data"));
   stream =  ??  //CFReadStreamCreateForHTTPRequest(NULL, message);
    CFRelease(message);
  //other headers...        
    if (CFWriteStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue)  == false)
    {
        NSLog(@"Error");
        return NO;
    }


    //
    // Open the stream
    //
    if (!CFWriteStreamOpen(stream))
    {
        CFRelease(stream);
        NSLog(@"Error");
        return NO;
    }

    CFStreamClientContext context = {0, self, NULL, NULL, NULL};
    CFWriteStreamSetClient(stram, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
                           RSWriteStreamCallBack,
                           &context);
    CFWriteStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);

Solution

  • The solution is create an subclass of NSInputStream, and implement the methods open, close, read, hasBytesAvailable and don't forget - (NSStreamStatus)streamStatus. Last method is invoked from http to know if we are open, close or we was finished (NSStreamStatusAtEnd) to send (there are others status, but this are the most important). I use a tmp file like buffer because I have to send a lot of data, but, perhaps, a data memory buffer could be better. Finally I implement other class where use my custom NSInputStream, here is the code:

        NSURL *url = [NSURL URLWithString:@"url"];
        NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
        [req setHTTPMethod:@"POST"];
        //set headers if you have to do for example: 
        NSString *contentType = [NSString stringWithFormat:@"multipart/form-data"];
        [req setValue:contentType forHTTPHeaderField:@"Content-Type"];
        //Create your own InputStream
        instream = [[CustomStream alloc] init];
        [req setHTTPBodyStream:instream];
        //I remove instream later 
          NSURLConnection *aConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO];
        [aConnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [aConnection start];