Enviar AVAudioRecorder al server iOS

Estoy intentando durante los últimos días cargar un logging local guardado en un server (que lo maneja con un file php y lo guarda en el server). El problema es que no puedo encontrar una manera de hacerlo.

Mientras graba el sonido (AVAudioRecorder) se guarda en un "NSTemporaryDirectory ()":

NSURL *temporaryRecFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"VoiceFile"]]]; 

Ahora, en todas partes que revisé la respuesta fue usar ASIHTTPRequest . pero el problema es que no es compatible con ios6.

Hay otras bibliotecas para ello, pero nada funciona sin importar qué y cómo lo intente. Me encantaría que alguien me ayudara …

Aquí está mi código:

ViewController.h

 #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> #import <CoreAudio/CoreAudioTypes.h> @interface ViewController : UIViewController <AVAudioRecorderDelegate,AVAudioPlayerDelegate> { UIButton *recordButton; UIButton *playButton; UIButton *uploadFile; UILabel *recStateLabel; BOOL isNotRecording; NSURL *temporaryRecFile; AVAudioRecorder *recorder; AVAudioPlayer *player; } @property (nonatomic,retain) IBOutlet UIButton *uploadFile; @property (nonatomic,retain) IBOutlet UIButton *playButton; @property (nonatomic,retain) IBOutlet UIButton *recordButton; @property (nonatomic,retain) IBOutlet UILabel *recStateLabel; -(IBAction)recording; -(IBAction)playback; -(IBAction)upload; @end 

ViewController.m

 #import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import "STHTTPRequest.h" @interface ViewController () @end @implementation ViewController @synthesize recordButton,playButton,uploadFile,recStateLabel; -(IBAction)recording { if(isNotRecording) { isNotRecording = NO; [recordButton setTitle:@"Stop" forState:UIControlStateNormal]; playButton.hidden = YES; recStateLabel.text = @"Recording"; temporaryRecFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"VoiceFile"]]]; NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey, [NSNumber numberWithInt:16], AVEncoderBitRateKey, [NSNumber numberWithInt: 2], AVNumberOfChannelsKey, [NSNumber numberWithFloat:44100.0], AVSampleRateKey, nil]; recorder = [[AVAudioRecorder alloc]initWithURL:temporaryRecFile settings:recordSettings error:nil]; [recorder setDelegate:self]; [recorder prepareToRecord]; [recorder record]; } else { isNotRecording = YES; [recordButton setTitle:@"Rec" forState:UIControlStateNormal]; playButton.hidden = NO; recStateLabel.text = @"Not Recording"; [recorder stop]; } } -(IBAction)playback { player = [[AVAudioPlayer alloc]initWithContentsOfURL:temporaryRecFile error:nil]; //player.volume = 1; [player setVolume: 1.0]; [player play]; } -(IBAction)upload { NSLog(@"upload"); recStateLabel.text = @"Uploading"; NSData *data = [NSData dataWithContentsOfFile:NSTemporaryDirectory()]; NSMutableString *urlString = [[NSMutableString alloc] initWithFormat:@""]; [urlString appendFormat:@"%@", data]; NSData *postData = [urlString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]]; NSString *baseurl = @"http://efron.org.il/dev/singsong/upload.php"; NSURL *url = [NSURL URLWithString:baseurl]; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; [urlRequest setHTTPMethod: @"POST"]; [urlRequest setValue:postLength forHTTPHeaderField:@"Content-Length"]; [urlRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [urlRequest setHTTPBody:postData]; NSURLConnection *connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self]; [connection start]; NSLog(@"Started!"); /* STHTTPRequest *r = [STHTTPRequest requestWithURLString:@"http://efron.org.il/dev/singsong/upload.php"]; r.completionBlock = ^(NSDictionary *headers, NSString *body) { // ... }; r.errorBlock = ^(NSError *error) { NSLog(@"error"); }; [r setFileToUpload:NSTemporaryDirectory() parameterName:@"sound"]; [r startAsynchronous]; ///................../// NSString *boundary = @"---------------------------14737809831466499882746641449"; NSMutableData *postData = [NSMutableData data]; NSString *header = [NSString stringWithFormat:@"--%@\r\n", boundary]; [postData appendData:[header dataUsingEncoding:NSUTF8StringEncoding]]; //add your filename entry NSString *contentDisposition = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", @"filename", @"iosaudio"]; [postData appendData:[contentDisposition dataUsingEncoding:NSUTF8StringEncoding]]; [postData appendData:[NSData dataWithContentsOfFile:NSTemporaryDirectory()]]; NSString *endItemBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n",boundary]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; [request setURL:[NSURL URLWithString:@"http://efron.org.il/dev/singsong/upload.php"]]; [postData appendData:[endItemBoundary dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:postData]; ///.........../// NSURL *url = [NSURL URLWithString:@"http://efron.org.il/"]; AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; NSData *songData = [NSData dataWithContentsOfURL:temporaryRecFile]; NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"dev/singsong/upload.php" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) { [formData appendPartWithFormData:songData name:@"file"]; }]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { recStateLabel.text = [NSString stringWithFormat:@"Sent %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite]; }]; [httpClient enqueueHTTPRequestOperation:operation]; */ } - (void)viewDidLoad { isNotRecording = YES; playButton.hidden = YES; recStateLabel.text = @"Not Recording"; AVAudioSession *audioSession = [AVAudioSession shanetworkingInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; [audioSession setActive:YES error:nil]; [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end 

El ViewController.m incluye algunas testings que he realizado con bibliotecas como STHTTPRequest y AFNetworking

esta linea de codigo me funciona bien

ahora he publicado mi código completo para grabar, save, reproducir y publicar en el server

Editado:

SoundRecordVC.h

 ///*********************** SoundRecordVC.h ***************************// #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface SoundRecordVC : UIViewController<AVAudioPlayerDelegate,AVAudioRecorderDelegate> { BOOL stopBtnFlag; BOOL pauseBtnFlag; NSTimer *timer; AVAudioPlayer *audioPlayer; AVAudioRecorder *audioRecorder; } // ------------------- Properties --------------------- @property (weak, nonatomic) IBOutlet UIButton *recordBtn; @property (weak, nonatomic) IBOutlet UIButton *playBtn; @property (strong, nonatomic) AVAudioRecorder *audioRecorder; @property (strong, nonatomic) AVAudioPlayer *audioPlayer; @property (strong,nonatomic) NSString *friendId; // ------------------- IBAction ----------------- - (IBAction)recordBtnPressed:(id)sender; - (IBAction)playBtnPressed:(id)sender; 

SoundRecordVC.m

 //*********************** SoundRecordVC.m ***************************// #import "SoundRecordVC.h" @interface SoundRecordVC.m () @end @implementation SoundRecordVC.m @synthesize recordBtn; @synthesize playBtn; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - #pragma mark - methods - (IBAction)recordBtnPressed:(id)sender { if (!stopBtnFlag) { if (!audioRecorder.recording) { [self performSelectorOnMainThread:@selector(setUpAudioRecorder) withObject:nil waitUntilDone:YES]; [audioRecorder record]; NSLog(@"Recording..."); } stopBtnFlag = YES; } else { [audioRecorder stop]; stopBtnFlag = NO; } } -(void)setUpAudioRecorder { AVAudioSession *audioSession = [AVAudioSession shanetworkingInstance]; [audioSession setCategory:AVAudioSessionCategoryRecord error:nil]; // --------------------- Setting for audio ----------------------// NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:AVAudioQualityMedium],AVEncoderAudioQualityKey,[NSNumber numberWithInt:16],AVEncoderBitRateKey,[NSNumber numberWithInt:2],AVNumberOfChannelsKey,[NSNumber numberWithInt:44100.0],AVSampleRateKey, nil]; NSError *error = nil; // --------------------- File save Path ----------------------// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/sounds.caf", documentsDirectory]]; audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&error]; audioRecorder.delegate = self; if ([audioRecorder prepareToRecord] == YES){ [audioRecorder prepareToRecord]; }else { int errorCode = CFSwapInt32HostToBig ([error code]); NSLog(@"Error: %@ [%4.4s])" , [error localizedDescription], (char*)&errorCode); } } - (IBAction)playBtnPressed:(id)sender { AVAudioSession *audioSession = [AVAudioSession shanetworkingInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; //----------------------loading files to player for playing------------------------------------// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/sounds.caf", documentsDirectory]]; NSError *error; NSLog(@"url is %@",url); [audioPlayer stop]; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; audioPlayer.numberOfLoops = 0; audioPlayer.delegate=self; [audioPlayer prepareToPlay]; if(!pauseBtnFlag){ NSLog(@"Playing......."); [audioPlayer play]; pauseBtnFlag=YES; }else{ NSLog(@"Pause"); [audioPlayer pause]; pauseBtnFlag=NO; } } #pragma mark - #pragma mark - AVRecorder Delegate -(void)audioRecorderDidFinishRecording: (AVAudioRecorder *)recorder successfully:(BOOL)flag { NSLog (@"audioRecorderDidFinishRecording:successfully"); NSLog(@"Stopped"); } -(void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error { NSLog(@"Encode Error occurnetworking"); } -(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { } -(void)dataUploadOnServer { NSLog(@"upload"); recStateLabel.text = @"Uploading"; NSString *baseurl = @"http://efron.org.il/dev/singsong/upload.php"; NSURL *dataURL = [NSURL URLWithString:baseurl]; NSMutableURLRequest *dataRqst = [NSMutableURLRequest requestWithURL:dataURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; [dataRqst setHTTPMethod:@"POST"]; NSString *stringBoundary = @"0xKhTmLbOuNdArY---This_Is_ThE_BoUnDaRyy---pqo"; NSString *headerBoundary = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",stringBoundary]; [dataRqst addValue:headerBoundary forHTTPHeaderField:@"Content-Type"]; NSMutableData *postBody = [NSMutableData data]; // -------------------- ---- Audio Upload Status ---------------------------\\ //pass MediaType file [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"Content-Disposition: form-data; name=\"Data\"; filename=\"myVoice.mp3\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"Content-Type: audio/caf\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"Content-Transfer-Encoding: binary\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; //*******************load locally store audio file********************// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *audioUrl = [NSString stringWithFormat:@"%@/record.mp3", documentsDirectory]; // get the audio data from main bundle directly into NSData object NSData *audioData; audioData = [[NSData alloc] initWithContentsOfFile:audioUrl]; // add it to body [postBody appendData:audioData]; [postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; // final boundary [postBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; // add body to post [dataRqst setHTTPBody:postBody]; NSHTTPURLResponse* response =[[NSHTTPURLResponse alloc] init]; NSError* error = [[NSError alloc] init] ; //synchronous filling of data from HTTP POST response NSData *responseData = [NSURLConnection sendSynchronousRequest:dataRqst returningResponse:&response error:&error]; //convert data into string NSString *responseString = [[NSString alloc] initWithBytes:[responseData bytes] length:[responseData length] encoding:NSUTF8StringEncoding]; NSLog(@"Response String %@",responseString); } #pragma mark - - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)viewDidUnload { [self setPlayBtn:nil]; [super viewDidUnload]; } 

@fin

Espero que funcione para ti

Algunos cambios para que todo funcione utilizando AFNetworking:

  • Use appendPartWithFileURL:name:fileName:mimeType:error: para evitar tener que cargar los datos de la canción en la memory.
  • Como lo sugiere @glenwayguy, use el patrón singleton para mantener una reference estática a su AFHTTPClient. De lo contrario, corre el riesgo de que las operaciones se desasignen prematuramente.
  • Debe usar AFHTTPClient -HTTPRequestOperationWithRequest:success:failure: para depurar la respuesta del server. Mencionaste que tu bloque de progreso de carga no estaba disparando; podría ser que su server regrese un error 500, 400 o 404.
  - (void)uploadAudio:(NSString *)audioPath jobId:(NSString *)jobIdStr{ FMResultSet *results = [database executeQuery:@"select * from AUDIOS where AUDIOLOC = ? and areqsync = 0 ",audioPath]; if(![results next]) { NSLog(@"Audio already uploaded"); } else{ NSLog(@"Audio is to be uploaded"); NSURL *audiourl=[NSURL URLWithString:audioPath]; NSLog(@"audio url and path are %@ --- %@",audiourl,audioPath); NSData *audioData=[NSData dataWithContentsOfFile:audiourl.path]; @try { NSLog(@"In upload audio function"); NSString *strURL = @"http://abc.com/data/default.aspx"; ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:strURL]]; request= [request initWithURL:[NSURL URLWithString:strURL]]; [request setShouldContinueWhenAppEntersBackground:YES]; [request setShouldAttemptPersistentConnection:YES]; [request setPostValue:jobIdStr forKey:@"lbljid"]; [request setPostValue:@"2" forKey:@"lblMtype"]; [request setPostValue:[Settings UserName] forKey:@"lblUsername"]; [request setPostValue:[Settings Password] forKey:@"lblpassword"]; [request addData:audioData withFileName:@"audio.caf" andContentType:@"audio/x-caf" forKey:@"filMyFile"]; [request setCompletionBlock:^{ BOOL success = [database executeUpdate:@"UPDATE AUDIOS SET areqsync = '1' WHERE AUDIOLOC = ?",audioPath ]; NSLog(success ? @"Audio Update to syncronised Yes" : @"Update to ended No"); [self requestFinished:request]; }]; //if request failed [request setFailedBlock:^{ [self requestFailed:request]; NSLog(@"request Failed: %@",[request error]); }]; [request startAsynchronous]; uploadCount++; } @catch (NSException *exception) { NSLog(@"Exception name and reson is %@ ------- %@",exception.name, exception.reason); } @finally { NSLog(@"finalyy of upload audio"); } }//end of if audio already sync } 

es posible que el problema principal con este código sea que en su bash actual (y en el código comentado en el bash de asignar NSData* songData cuando se utiliza AFNetworking) es que la línea de código que se upload en el método se debe cambiar de:

  NSData *data = [NSData dataWithContentsOfFile:NSTemporaryDirectory()]; 

a esto:

  NSData *data = [NSData dataWithContentsOfFile:temporaryRecFile];