【问题标题】:Sending AVAudioRecorder to server iOS将 AVAudioRecorder 发送到服务器 iOS
【发布时间】:2013-05-25 23:45:10
【问题描述】:

过去几天我一直在尝试将本地保存的声音记录上传到服务器(服务器使用 php 文件处理它并将其保存到服务器)。 问题是我找不到办法。

在录制声音(AVAudioRecorder)时,它会保存在“NSTemporaryDirectory()”中:

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

现在,我检查的所有地方都是使用ASIHTTPRequest。 但问题是ios6不支持。

还有一些其他的库,但无论我如何尝试,都没有任何效果。 如果有人可以帮助我,我会很高兴...

这是我的代码:

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

ViewController.m 包含一些我使用诸如 STHTTPRequest 和 AFNetworking 之类的库所做的测试

【问题讨论】:

  • 在尝试时,比如说 AFNetwroking,有什么问题?有错误吗?什么都没有发生?我们需要更多信息来问候您。
  • 它正在上传文件。我已经更新了一个名为“recStateLabel”的UILabel,其中发送了多少:recStateLabel.text = [NSString stringWithFormat:@"Sent %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite];,它什么也没做……我没有得到服务器的响应,文件也没有上传到目录。 PHP 文件可以正常工作,因为 Android 上的应用程序可以完美地使用它
  • 一件事是您可能使用错误的 AFNetworking。您应该为每个 API 子类化 AFHttpCLient,并且您总是应该使用单例。
  • 我应该怎么做呢?你看到的是我在网站上找到的答案并对其进行了修改。
  • 这个网站上的一些答案可能是错误的。

标签: ios objective-c asihttprequest afnetworking avaudiorecorder


【解决方案1】:

这行代码很适合我

现在我已经发布了用于录制、保存、播放和发布到服务器的全部代码

已编辑:-

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

@结束

希望对你有用

【讨论】:

  • 如果有任何疑问请向我提问
  • 它似乎返回了响应,因此它确实尝试上传,但响应是“上传文件时出错,请重试!”所以这意味着文件没有保存。在您的代码中,您是否调用了声音文件?以及在录制时如何以及在哪里保存?
  • 检查您的音频文件是否保存在本地
  • 文件保存在 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  • n 请检查您的网址。当 URL 在服务器上没有上传之前点击浏览器时,会显示相同的错误消息“上传文件时出错,请重试!”
【解决方案2】:

使用 AFNetworking 进行一些更改以使一切正常工作:

  • 使用appendPartWithFileURL:name:fileName:mimeType:error: 避免将歌曲数据加载到内存中。
  • 按照@glenwayguy 的建议,使用单例模式来保持对AFHTTPClient 的静态引用。否则,您可能会面临过早解除分配操作的风险。
  • 您应该使用AFHTTPClient -HTTPRequestOperationWithRequest:success:failure: 来调试服务器响应。您提到您的上传进度块没有触发;可能是您的服务器返回 500、400 或 404 错误。

【讨论】:

  • 嘿@mattt!你能上传一个关于它应该如何的示例代码吗?我正在尝试做一些事情,但无法理解一些输入。谢谢。
【解决方案3】:
 - (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
 }

【讨论】:

  • 这段代码使用的是“ASIFormDataRequest”,它是link 的一部分,过去两年没有更新,也不支持ios6...对我没有太大帮助.. .
【解决方案4】:

此代码的主要问题可能是在其当前尝试中(以及在使用 AFNetworking 时尝试分配 NSData* songData 的注释掉代码中)是方法 upload 中的代码行应该更改自:

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

到这里:

    NSData *data = [NSData dataWithContentsOfFile:temporaryRecFile];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    相关资源
    最近更新 更多