PHAsset + AFNetworking。 无法将file upload到真实设备上的服务器

目前我正在使用下面的代码上传文件到服务器

NSURLRequest *urlRequest = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:[[entity uploadUrl]absoluteString] parameters:entity.params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { // Get file url [UploadModel getAassetUrl:entity.asset resultHandler:^(NSURL *fileUrl) { NSError *fileappenderror; // Append [formData appendPartWithFileURL:fileUrl name:@"data" error:&fileappenderror]; if (fileappenderror) { [Sys MyLog: [fileappenderror localizedDescription] ]; } }]; } error:&urlRequestError]; 

/ * getAassetUrl * /

 +(void)getAassetUrl: (PHAsset*)mPhasset resultHandler:(void(^)(NSURL *imageUrl))dataResponse{ PHImageRequestOptions * requestOption = [[PHImageRequestOptions alloc] init]; requestOption.synchronous = YES; requestOption.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat; [[PHImageManager defaultManager] requestImageDataForAsset:mPhasset options:requestOption resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { dataResponse([info objectForKey:@"PHImageFileURLKey"]); }]; } 

这种方法在模拟器上工作,但在真实设备上失败:空file upload到服务器很可能是由于从本地存储器读取失败。 日志显示通知

注意:Sandbox:MyApp(213)拒绝file-read-data /private/var/mobile/Media/DCIM/101APPLE/IMG_1570.PNG

我相信这个说明意味着应用程序不能通过指定的path访问文件。 此外,我已经尝试了另一种方法,通过附加从请求PHAsset数据返回的NSData上传文件。 但是这种方法在大型媒体文件的情况下是不可用的。 因为整个文件被加载到内存中。

有什么想法吗?

requestImageDataForAsset返回的NSData对象是内存映射 – 所以整个文件不会被加载到内存中。 所以这种方法将没有任何问题的图像。

对于video,你应该使用适当的方法requestExportSessionForVideorequestAVAssetForVideo如果你可以限制你的部署目标到iOS 9,你也应该看看PHAssetResourceManager

对于大文件,不应该使用requestImageDataForAsset(_:options:resultHandler:) 。 原因是您不想将整个媒体文件加载到内存中,您将很快耗尽内存,应用程序将崩溃。 这通常意味着您不应该将其用于大型图像或几乎任何video。

根据我的经验,尝试直接从PHAsset资源url上传将会失败。 苹果似乎没有授予我们从PHAsset源文件直接上传所需的权限。 在这里看论坛post。 这是一个痛苦,因为如果我们想要上传video,它会迫使我们使用大量额外的磁盘空间。

为了获得您打算上传的video文件的本地文件url,您需要使用以下两种方法之一:

requestExportSessionForVideo(_:options:exportPreset:resultHandler:)

要么

requestAVAssetForVideo(_:options:resultHandler:)

您将使用这些方法将video文件的副本导出到您控制的磁盘上的某个位置。 并从该file upload。 奖金function:如果需要,这两种方法都将从iCloud下载文件。

查看VimeoUpload库,了解与video上传相关的所有内容。 免责声明:我是图书馆的作者之一。

即使您没有上传到Vimeo服务器,也可以使用ExportOperation包含的PHAssetExportSessionOperationExportOperation类来完成您想要的操作。 有关获取PHAsset的文件URL的详细信息,请参阅repo README。 它还包括用于获取ALAsset的文件URL的工具 。

如果您对使用PHAssetExportSessionOperationExportOperation不感兴趣,请查看它们的实现,以获取有关如何在PHAssetExportSessionOperation使用Apple类的详细信息。