QNPHAssetFile.m 5.47 KB
Newer Older
zhukai committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
//
//  QNPHAssetFile.m
//  Pods
//
//  Created by   何舒 on 15/10/21.
//
//

#import "QNPHAssetFile.h"

#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
#import <AVFoundation/AVFoundation.h>
#import <Photos/Photos.h>

#import "QNResponseInfo.h"

@interface QNPHAssetFile ()

@property (nonatomic) PHAsset *phAsset;

@property (readonly) int64_t fileSize;

@property (readonly) int64_t fileModifyTime;

@property (nonatomic, strong) NSData *assetData;

@property (nonatomic, strong) NSURL *assetURL;

@property (nonatomic, readonly) NSString *filepath;

@property (nonatomic) NSFileHandle *file;

@end

@implementation QNPHAssetFile

- (instancetype)init:(PHAsset *)phAsset error:(NSError *__autoreleasing *)error {
    if (self = [super init]) {
        NSDate *createTime = phAsset.creationDate;
        int64_t t = 0;
        if (createTime != nil) {
            t = [createTime timeIntervalSince1970];
        }
        _fileModifyTime = t;
        _phAsset = phAsset;
        _filepath = [self getInfo];
        if (PHAssetMediaTypeVideo == self.phAsset.mediaType) {
            NSError *error2 = nil;
            NSDictionary *fileAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:_filepath error:&error2];
            if (error2 != nil) {
                if (error != nil) {
                    *error = error2;
                }
                return self;
            }
            _fileSize = [fileAttr fileSize];
            NSFileHandle *f = nil;
            NSData *d = nil;
            if (_fileSize > 16 * 1024 * 1024) {
                f = [NSFileHandle fileHandleForReadingAtPath:_filepath];
                if (f == nil) {
                    if (error != nil) {
                        *error = [[NSError alloc] initWithDomain:_filepath code:kQNFileError userInfo:nil];
                    }
                    return self;
                }
            } else {
                d = [NSData dataWithContentsOfFile:_filepath options:NSDataReadingMappedIfSafe error:&error2];
                if (error2 != nil) {
                    if (error != nil) {
                        *error = error2;
                    }
                    return self;
                }
            }
            _file = f;
            _assetData = d;
        }
    }
    return self;
}

- (NSData *)read:(long)offset size:(long)size {
    if (_assetData != nil) {
        return [_assetData subdataWithRange:NSMakeRange(offset, (unsigned int)size)];
    }
    [_file seekToFileOffset:offset];
    return [_file readDataOfLength:size];
}

- (NSData *)readAll {
    return [self read:0 size:(long)_fileSize];
}

- (void)close {
    if (PHAssetMediaTypeVideo == self.phAsset.mediaType) {
        if (_file != nil) {
            [_file closeFile];
        }
        [[NSFileManager defaultManager] removeItemAtPath:_filepath error:nil];
    }
}

- (NSString *)path {
    return _filepath;
}

- (int64_t)modifyTime {
    return _fileModifyTime;
}

- (int64_t)size {
    return _fileSize;
}

- (NSString *)getInfo {
    __block NSString *filePath = nil;
    if (PHAssetMediaTypeImage == self.phAsset.mediaType) {
        PHImageRequestOptions *options = [PHImageRequestOptions new];
        options.version = PHImageRequestOptionsVersionCurrent;
        options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
        options.resizeMode = PHImageRequestOptionsResizeModeNone;
        //不支持icloud上传
        options.networkAccessAllowed = NO;
        options.synchronous = YES;

        [[PHImageManager defaultManager] requestImageDataForAsset:self.phAsset
                                                          options:options
                                                    resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
                                                        _assetData = imageData;
                                                        _fileSize = imageData.length;
                                                        _assetURL = [NSURL URLWithString:self.phAsset.localIdentifier];
                                                        filePath = _assetURL.path;
                                                    }];
    } else if (PHAssetMediaTypeVideo == self.phAsset.mediaType) {
        NSArray *assetResources = [PHAssetResource assetResourcesForAsset:self.phAsset];
        PHAssetResource *resource;
        for (PHAssetResource *assetRes in assetResources) {
            if (assetRes.type == PHAssetResourceTypePairedVideo || assetRes.type == PHAssetResourceTypeVideo) {
                resource = assetRes;
            }
        }
        NSString *fileName = @"tempAssetVideo.mov";
        if (resource.originalFilename) {
            fileName = resource.originalFilename;
        }
        PHAssetResourceRequestOptions *options = [PHAssetResourceRequestOptions new];
        //不支持icloud上传
        options.networkAccessAllowed = NO;

        NSString *PATH_VIDEO_FILE = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
        [[NSFileManager defaultManager] removeItemAtPath:PATH_VIDEO_FILE error:nil];
        [[PHAssetResourceManager defaultManager] writeDataForAssetResource:resource toFile:[NSURL fileURLWithPath:PATH_VIDEO_FILE] options:options completionHandler:^(NSError *_Nullable error) {
            if (error) {
                filePath = nil;
            } else {
                filePath = PATH_VIDEO_FILE;
            }
        }];
    }
    return filePath;
}

@end
#endif