11
11
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
12
12
#import < AVFoundation/AVFoundation.h>
13
13
#import < Photos/Photos.h>
14
- enum {
15
- kAMASSETMETADATA_PENDINGREADS = 1 ,
16
- kAMASSETMETADATA_ALLFINISHED = 0
17
- };
18
14
19
15
#import " QNResponseInfo.h"
20
16
21
- @interface QNPHAssetFile () {
22
- BOOL _hasGotInfo;
23
- }
17
+ @interface QNPHAssetFile ()
24
18
25
19
@property (nonatomic ) PHAsset *phAsset;
26
20
@@ -32,6 +26,10 @@ @interface QNPHAssetFile () {
32
26
33
27
@property (nonatomic , strong ) NSURL *assetURL;
34
28
29
+ @property (nonatomic , readonly ) NSString *filepath;
30
+
31
+ @property (nonatomic ) NSFileHandle *file;
32
+
35
33
@end
36
34
37
35
@implementation QNPHAssetFile
@@ -45,30 +43,69 @@ - (instancetype)init:(PHAsset *)phAsset error:(NSError *__autoreleasing *)error
45
43
}
46
44
_fileModifyTime = t;
47
45
_phAsset = phAsset;
48
- [self getInfo ];
46
+ _filepath = [self getInfo ];
47
+ if (PHAssetMediaTypeVideo == self.phAsset .mediaType ) {
48
+ NSError *error2 = nil ;
49
+ NSDictionary *fileAttr = [[NSFileManager defaultManager ] attributesOfItemAtPath: _filepath error: &error2];
50
+ if (error2 != nil ) {
51
+ if (error != nil ) {
52
+ *error = error2;
53
+ }
54
+ return self;
55
+ }
56
+ _fileSize = [fileAttr fileSize ];
57
+ NSFileHandle *f = nil ;
58
+ NSData *d = nil ;
59
+ if (_fileSize > 16 * 1024 * 1024 ) {
60
+ f = [NSFileHandle fileHandleForReadingAtPath: _filepath];
61
+ if (f == nil ) {
62
+ if (error != nil ) {
63
+ *error = [[NSError alloc ] initWithDomain: _filepath code: kQNFileError userInfo: nil ];
64
+ }
65
+ return self;
66
+ }
67
+ } else {
68
+ d = [NSData dataWithContentsOfFile: _filepath options: NSDataReadingMappedIfSafe error: &error2];
69
+ if (error2 != nil ) {
70
+ if (error != nil ) {
71
+ *error = error2;
72
+ }
73
+ return self;
74
+ }
75
+ }
76
+ _file = f;
77
+ _assetData = d;
78
+ }
79
+
49
80
}
50
81
return self;
51
82
}
52
83
53
84
- (NSData *)read : (long )offset size : (long )size {
54
- NSRange subRange = NSMakeRange (offset, size);
55
- if (!self.assetData ) {
56
- self.assetData = [self fetchDataFromAsset: self .phAsset];
85
+ if (_assetData != nil ) {
86
+ return [_assetData subdataWithRange: NSMakeRange (offset, (unsigned int )size)];
57
87
}
58
- NSData *subData = [self .assetData subdataWithRange: subRange];
59
-
60
- return subData;
88
+ [_file seekToFileOffset: offset];
89
+ return [_file readDataOfLength: size];
61
90
}
62
91
63
92
- (NSData *)readAll {
64
93
return [self read: 0 size: (long )_fileSize];
65
94
}
66
95
67
96
- (void )close {
97
+ if (PHAssetMediaTypeVideo == self.phAsset .mediaType ) {
98
+ if (_file != nil ) {
99
+ [_file closeFile ];
100
+
101
+ }
102
+ [[NSFileManager defaultManager ] removeItemAtPath: _filepath error: nil ];
103
+
104
+ }
68
105
}
69
106
70
107
- (NSString *)path {
71
- return self. assetURL . path ;
108
+ return _filepath ;
72
109
}
73
110
74
111
- (int64_t )modifyTime {
@@ -79,91 +116,53 @@ - (int64_t)size {
79
116
return _fileSize;
80
117
}
81
118
82
- - (void )getInfo {
83
- if (!_hasGotInfo) {
84
- _hasGotInfo = YES ;
85
-
86
- if (PHAssetMediaTypeImage == self. phAsset . mediaType ) {
87
- PHImageRequestOptions *request = [PHImageRequestOptions new ] ;
88
- request. version = PHImageRequestOptionsVersionCurrent ;
89
- request. deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
90
- request. resizeMode = PHImageRequestOptionsResizeModeNone ;
91
- request .synchronous = YES ;
119
+ - (NSString * )getInfo {
120
+ __block NSString * filePath = nil ;
121
+ if (PHAssetMediaTypeImage == self. phAsset . mediaType ) {
122
+ PHImageRequestOptions *options = [PHImageRequestOptions new ];
123
+ options. version = PHImageRequestOptionsVersionCurrent;
124
+ options. deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat ;
125
+ options. resizeMode = PHImageRequestOptionsResizeModeNone ;
126
+ // 不支持icloud上传
127
+ options. networkAccessAllowed = NO ;
128
+ options .synchronous = YES ;
92
129
93
130
[[PHImageManager defaultManager ] requestImageDataForAsset: self .phAsset
94
- options: request
131
+ options: options
95
132
resultHandler: ^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
133
+ _assetData = imageData;
96
134
_fileSize = imageData.length ;
97
135
_assetURL = [NSURL URLWithString: self .phAsset.localIdentifier];
136
+ filePath = _assetURL.path ;
98
137
}];
99
138
} else if (PHAssetMediaTypeVideo == self.phAsset .mediaType ) {
100
- PHVideoRequestOptions *request = [PHVideoRequestOptions new ];
101
- request.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
102
- request.version = PHVideoRequestOptionsVersionCurrent;
103
-
104
- NSConditionLock *assetReadLock = [[NSConditionLock alloc ] initWithCondition: kAMASSETMETADATA_PENDINGREADS ];
105
- [[PHImageManager defaultManager ] requestPlayerItemForVideo: self .phAsset options: request resultHandler: ^(AVPlayerItem *playerItem, NSDictionary *info) {
106
- AVURLAsset *urlAsset = (AVURLAsset *)playerItem.asset ;
107
- NSNumber *fileSize = nil ;
108
- [urlAsset.URL getResourceValue: &fileSize forKey: NSURLFileSizeKey error: nil ];
109
- _fileSize = [fileSize unsignedLongLongValue ];
110
- _assetURL = urlAsset.URL ;
111
-
112
- [assetReadLock lock ];
113
- [assetReadLock unlockWithCondition: kAMASSETMETADATA_ALLFINISHED ];
139
+ NSArray * assetResources = [PHAssetResource assetResourcesForAsset: self .phAsset];
140
+ PHAssetResource * resource;
141
+ for (PHAssetResource * assetRes in assetResources) {
142
+ if (assetRes.type == PHAssetResourceTypePairedVideo || assetRes.type == PHAssetResourceTypeVideo) {
143
+ resource = assetRes;
144
+ }
145
+ }
146
+ NSString * fileName = @" tempAssetVideo.mov" ;
147
+ if (resource.originalFilename ) {
148
+ fileName = resource.originalFilename ;
149
+ }
150
+ PHVideoRequestOptions * options = [[PHVideoRequestOptions alloc ] init ];
151
+ options.version = PHImageRequestOptionsVersionCurrent;
152
+ // 不支持icloud上传
153
+ options.networkAccessAllowed = NO ;
154
+ options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
155
+ NSString * PATH_VIDEO_FILE = [NSTemporaryDirectory () stringByAppendingPathComponent: fileName];
156
+ [[NSFileManager defaultManager ] removeItemAtPath: PATH_VIDEO_FILE error: nil ];
157
+ [[PHAssetResourceManager defaultManager ] writeDataForAssetResource: resource toFile: [NSURL fileURLWithPath: PATH_VIDEO_FILE] options: options completionHandler: ^(NSError * _Nullable error) {
158
+ if (error) {
159
+ filePath = nil ;
160
+ } else {
161
+ filePath = PATH_VIDEO_FILE;
162
+ }
114
163
}];
115
- [assetReadLock lockWhenCondition: kAMASSETMETADATA_ALLFINISHED ];
116
- [assetReadLock unlock ];
117
- assetReadLock = nil ;
118
- }
119
- }
120
- }
121
-
122
- - (NSData *)fetchDataFromAsset : (PHAsset *)asset {
123
- __block NSData *tmpData = [NSData data ];
124
-
125
- // Image
126
- if (asset.mediaType == PHAssetMediaTypeImage) {
127
- PHImageRequestOptions *request = [PHImageRequestOptions new ];
128
- request.version = PHImageRequestOptionsVersionCurrent;
129
- request.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
130
- request.resizeMode = PHImageRequestOptionsResizeModeNone;
131
- request.synchronous = YES ;
132
-
133
- [[PHImageManager defaultManager ] requestImageDataForAsset: asset
134
- options: request
135
- resultHandler:
136
- ^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
137
- tmpData = [NSData dataWithData: imageData];
138
- }];
139
164
}
140
- // Video
141
- else {
142
-
143
- PHVideoRequestOptions *request = [PHVideoRequestOptions new ];
144
- request.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
145
- request.version = PHVideoRequestOptionsVersionCurrent;
146
-
147
- NSConditionLock *assetReadLock = [[NSConditionLock alloc ] initWithCondition: kAMASSETMETADATA_PENDINGREADS ];
148
-
149
- [[PHImageManager defaultManager ] requestAVAssetForVideo: asset
150
- options: request
151
- resultHandler:
152
- ^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
153
- AVURLAsset *urlAsset = (AVURLAsset *)asset;
154
- NSData *videoData = [NSData dataWithContentsOfURL: urlAsset.URL];
155
- tmpData = [NSData dataWithData: videoData];
156
-
157
- [assetReadLock lock ];
158
- [assetReadLock unlockWithCondition: kAMASSETMETADATA_ALLFINISHED ];
159
- }];
160
-
161
- [assetReadLock lockWhenCondition: kAMASSETMETADATA_ALLFINISHED ];
162
- [assetReadLock unlock ];
163
- assetReadLock = nil ;
164
- }
165
-
166
- return tmpData;
165
+ return filePath;
167
166
}
168
167
169
168
@end
0 commit comments