PHP скачать большой музыкальный двоичный файл base64_encode / bas64_decode для IOS

Я пытаюсь POST с iOS на мой сервер PHP и заставить сервер PHP вернуть двоичный файл в мое приложение iOS, используя base64_encode для передачи.

Файл загружается на мое устройство iOS, но AVAsset сообщает, что файл не воспроизводится, и я не могу понять, где моя ошибка. Я также уверен, что каждое из названий является действительными файлами .wav и .mp3 на сервере.

соответствующая часть PHP-файла:

    $song_to_download = $_POST['title'];
...(check if file exists, open 'rb', etc)

while (!feof($fp))
{
$block = fread($fp, 57 * 143); // based on php.net base64_encode examples
$base64 = base64_encode($block);
print $base64;
}

соответствующий код iOS:

- (NSUInteger) getFileSizeLocal:(NSString *)path
{
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
NSDictionary *dict = [fm attributesOfItemAtPath:path error:&error];
if (dict == nil)
{
NSLog(@"getFileSize - ERROR reading file attributes <%@>", error.localizedDescription);
return 0;
}
return [dict[NSFileSize] unsignedIntegerValue];
}

-(void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location
{
// decode the base64 'location' file and write it to the final file
NSString *path = location.absoluteString;
if (path.length < 8) {
NSLog(@"ERROR - <%@> length is less than 8", path);
return;
}
NSInteger fileStrLen = 7;   // 'file://' length - we keep the first / so its a complete hard path in the filesystem
NSString *filepath = [path substringWithRange:NSMakeRange(fileStrLen, path.length - fileStrLen)]; // strip off 'file://' portion first

if ([[NSFileManager defaultManager] fileExistsAtPath:filepath] == NO)
{
NSLog(@"ERROR - file does NOT exists at path <%@>", filepath);
return;
}

NSFileHandle *fpi = [NSFileHandle fileHandleForReadingAtPath:filepath];

NSUInteger len = [self getFileSizeLocal:filepath];
if (len == 0) {
NSLog(@"ERROR - filesize is zero");
return;
}
NSFileHandle *fpo = [NSFileHandle fileHandleForWritingAtPath:_largePathAndFileToWrite];
if (fpo == nil)
{
[[NSFileManager defaultManager] createFileAtPath:_largePathAndFileToWrite contents:nil attributes:nil];
fpo = [NSFileHandle fileHandleForWritingAtPath:_largePathAndFileToWrite];
}

// Read tmp input file (filepath), WRITE to final filename (_largePathAndFileToWrite)
NSData *data = nil;
NSData *decoded64Data = nil;
NSString *base64String = nil;
NSUInteger step_size = 10868; // based on php.net base64_encode examples

@autoreleasepool
{
for (NSUInteger x = 0; x < len; x += step_size)
{
data = [fpi readDataOfLength:step_size];
base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
decoded64Data = [base64String dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

if (decoded64Data == nil)
{
NSLog(@"ERROR - failed to decode data from tmp input file at idx <%ld>", (long)x);
break;
}
[fpo seekToEndOfFile];
[fpo writeData:decoded64Data];
}
}
[fpo closeFile];
[fpi closeFile];

NSURL *fileURL = [NSURL fileURLWithPath:_largePathAndFileToWrite];
AVAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
if (asset.isPlayable) {
NSLog(@"GOOD");
}
if (asset.isReadable) {
NSLog(@"READABLE");
}
else {
NSLog(@"Asset is BAD %@", _largePathAndFileToWrite);
}
}

Мой вывод всегда говорит «Актив плохой»

Размеры файлов, которые я пробую, составляют менее 50 Мбайт, а размер
сервер того же размера, что и конечный файл на устройстве iOS после
скачать.

Когда я пытался воспроизвести его с AVAudioPlayer, он всегда терпел неудачу:

The operation couldn't be completed.

Любая помощь приветствуется. Я провел несколько часов, пытаясь понять это.

Заранее спасибо!

[Решено]

Я пытался сделать это трудным путем. Оказывается, я могу передать это
как двоичный файл без base64 кодирования. Вот окончательное решение для
всем, кому это тоже нужно

Сторона PHP: (работает для .mp3 .wav .m4a, другие не пробовали)

<?php

$filepath = "./slist/mysong.mp3";

if (file_exists($filepath)) {
header('Content-Type: application/octect-stream');
header('Content-Description: File Transfer');
header('Content-Length: ' . filesize($filepath));
ob_clean();
flush();
readfile($filepath);
}
?>

Код IOS:

-(void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location
{
NSLog(@"downloadTask - didFinishDownloadingToURL <%@>", location.absoluteString);

// decode the base64 'location' file and write it to the final file
NSString *path = location.absoluteString;
if (path.length < 8) {
NSLog(@"ERROR - <%@> length is less than 8", path);
return;
}
NSInteger fileStrLen = 7;   // 'file://' length - we keep the first / so its a complete hard path in the filesystem
NSString *filepath = [path substringWithRange:NSMakeRange(fileStrLen, path.length - fileStrLen)]; // strip off 'file://' portion first

if ([[NSFileManager defaultManager] fileExistsAtPath:filepath] == NO)
{
NSLog(@"ERROR - file does NOT exists at path <%@>", filepath);
return;
}

// Just Move it into place
NSError *error;
if ([[NSFileManager defaultManager] moveItemAtPath:filepath toPath:_largePathAndFileToWrite error:&error] == NO)
{
NSLog(@"ERROR - failed to move file - <%@>", error.localizedDescription);
return;
}
}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …