5

I am trying for the past few days to upload a locally saved sounde record to a server (which handels it with a php file and saves it to the server). the problem is that I can't find a way to do that.

While recording the sound (AVAudioRecorder) it saves at a "NSTemporaryDirectory()":

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

Now, everywhere I checked the answer was to use ASIHTTPRequest. but the problem is that it is not supported in ios6.

There are some other libraries for it but nothing works no matter what and how I try. I would love it if someone could help me...

Here is my code:

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 sharedInstance];
    [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

The ViewController.m includes some test I have made with libraries such as STHTTPRequest and AFNetworking

icodebuster
  • 8,890
  • 7
  • 62
  • 65
Eliran Efron
  • 621
  • 5
  • 16
  • When trying, say AFNetwroking, what is the problem? Is there an error? Does nothing happen? We need a little more info to hello you. – charleyh May 26 '13 at 03:51
  • it is uploading the file. i have updated a `UILabel` named 'recStateLabel' with how many of how many was sent: `recStateLabel.text = [NSString stringWithFormat:@"Sent %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite];` and it does nothing... i don't get response from the server and the file is not uploded to the directory. the PHP file works because the app on the Android works with it perfectly – Eliran Efron May 26 '13 at 08:07
  • One thing is that you might be using AFNetworking wrong. Your supposed to subclass AFHttpCLient for every API, and you're always supposed to use a singleton. – charleyh May 26 '13 at 14:16
  • And how am i suposed to do that? what you see there is an answer i found on the site and slitly modified it. – Eliran Efron May 26 '13 at 19:38
  • Some answers on this site can be wrong. – charleyh May 26 '13 at 19:56
  • Also, the one answer is by one of the main people in developing AFNetworking. @mattt is right – charleyh May 26 '13 at 19:57

4 Answers4

4

this line of code works for me fine

now I have post my whole code for Record,save,play & post to server

Edited:-

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 sharedInstance];
    [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 sharedInstance];
    [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 occurred");
}

-(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];
}

@end

i hope it will works for u

Kanhaiya Sharma
  • 1,040
  • 8
  • 20
2

A few changes to get everything working using AFNetworking:

  • Use appendPartWithFileURL:name:fileName:mimeType:error: to avoid having to load your song data into memory.
  • As suggested by @glenwayguy, use the singleton pattern to keep a static reference to your AFHTTPClient. Otherwise, you risk having operations prematurely deallocated.
  • You should use AFHTTPClient -HTTPRequestOperationWithRequest:success:failure: to debug server response. You mentioned that your upload progress block was not firing; it could be that your server is returning a 500, 400, or 404 error.
Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
mattt
  • 19,544
  • 7
  • 73
  • 84
  • hey @mattt! can you upload a sample code about how it should be? i am trying to do some things and can't understand some inputs. thanks. – Eliran Efron May 26 '13 at 20:41
0
 - (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
 }
TechFanatic
  • 1,218
  • 4
  • 13
  • 31
  • this code is using "ASIFormDataRequest" which is a part of [link](http://allseeing-i.com/ASIHTTPRequest/) which is not updated for the past two years and doesn't support ios6... didn't help me that much... – Eliran Efron May 28 '13 at 14:32
0

it's possible that the primary problem with this code is that in its current attempt (and in the commented out code in the attempt to assign NSData* songData when using AFNetworking) is that the line of code that in method upload should be changed from:

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

to this:

    NSData *data = [NSData dataWithContentsOfFile:temporaryRecFile];
john.k.doe
  • 7,533
  • 2
  • 37
  • 64