需求是这样的。用户可以一次在本地选择 最多 2G的视频加照片上传到服务器
由于文件太大,只能通过获取文件的本地路径,然后通过OSS直接上传到阿里云。
刚开始的做法是:
通过 框架获取的视频信息。
之后通过
[[PHImageManager defaultManager] requestAVAssetForVideo:asset
options:videoOptions resultHandler:^(AVAsset * _Nullable avasset,
AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
}];
和
[[PHImageManager defaultManager] requestImageDataForAsset:asset
options:options resultHandler:^(NSData * _Nullable imageData,
NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
}];
获取资源数据,之后截取 info[@"PHImageFileSandboxExtensionTokenKey"] 然后一系列操作之后,获取资源的 本地路径。然后开始上传。
刚开始在iOS12的手机上,针对照片和视频都能实现上传。
后来经过测试,在iOS12 以下的系统版本。
当上传的是照片时,会因为权限问题,无法访问本地路径对应的文件。
错误信息类似于
Error Domain=NSCocoaErrorDomain Code=257 "
The operation couldn’t be completed. (Cocoa error 257.)"
UserInfo=0x17762480 {NSFilePath=/var/mobile/Media/DCIM/100APPLE/IMG_0291.PNG,
NSUnderlyingError=0x17741d10 "The operation couldn’t be completed. Operation not permitted"}
这个可以解决,因为一次只开启三个上传任务。可以在上传的时候,获取图片的data,缓存到内存里进行上传。
后来神坑出现了。
当iOS12以下的设备上传的是视频时。可以通过路径访问到视频文件,
但是一旦开始异步上传路径对应的文件。
OSS 会抛出以下错误。
ErrorMessage=File doesn't exist
经过大量的测试,得出结论。
上传视频的时候,直接引用路径是不够的。
首先
[[PHImageManager defaultManager]requestAVAssetForVideo:options:resultHandler:]
的方法里面会返回出 AVAsset 类的对象。我们可以通过 AVAsset 播放视频。同时也会有对该文件读的权限。
但是一旦 AVAsset 对象释放了, 读的权限也就没了。
因此需要对AVAsset进行强引用,上传完成之后再释放。就OK了。