iosobjective-ccore-audioasihttprequest

Sending .caf to server with ASIHTTPRequest


I am using AVAssetReader to create a .caf file that can play locally on my computer. However, when I try to upload the .caf to a server, the uploaded file can no longer be read. Here is my code:

NSLog(@"Posting to server");
NSURL *serverURL = [NSURL URLWithString:serverString];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:serverURL];
[request setRequestMethod:@"POST"];
[request setData:songData
    withFileName:@"exported.caf"
  andContentType:@"audio/x-caf"
          forKey:@"musicfile"];
[request setDelegate:self];
[request startAsynchronous];

Interesting, when I do the following, the generated file works on my computer:

NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *storePath = [applicationDocumentsDir stringByAppendingPathComponent:@"test.caf"];
[songData writeToFile:storePath atomically:NO];

Do I have to append some type of header to the musicData to get the .caf to be formatted properly?


Solution

  • here are some trouble shooting notes to identify the problem:

    1. ensure that you are playing the song in the server using the exact same audio reader app that you used to play it locally (ie eliminate the possibility that the server audio app has the appropriate decoder to read a .caf file. You can easily troubleshoot that by trying to play an original (ie one you didn't create yourself, one that's proven to work) .caf file on the remote server.

    2. whenever you face a problem that you have trouble identifying the cause.. then take a step back and use first principles. In this case.. download a hex editor like hexfiend and compare the file you got locally that can be read with the one on the server.. if you see any discrepancy in values, that means that the values got messed up during the transfer. This happens because of the whole big endian/ small endian network transfer issue (you can find a good discussion of what big/small endian means here, you resolve this issue by using functions like CFSwapInt16BigToHost etc (used as an example.. it may not be the one you end up having to use).

    3. you are using ASIHTTPRequest API.. which is a wrapper around the CFNetwork API. It's stated purpose is to make your life easier, but in this case if too much is hidden under the hood (ie you can't easily debug the problem), that purpose is no longer fulfilled. If that's the case, I suggest you jump a layer deeper and use CFNetwork API directly. (It's not that hard, and is definitely easier to debug).