php将大型音乐二进制文件base64_encode / bas64_decode下载到IOS

时间:2018-09-06 22:39:47

标签: php ios base64 nsurlconnection avaudioplayer

我正在尝试从iOS发布到我的PHP服务器,并让PHP服务器使用base64_encode将二进制文件返回到我的iOS应用。

该文件下载到我的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);
    }
}

我的输出始终显示“资产不佳”

我正在尝试的文件大小小于50M字节,并且 服务器的大小与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 个答案:

没有答案