PHAsset + AFNetworking。无法将文件上传到真实设备上的服务器

时间:2015-10-06 03:59:18

标签: ios objective-c iphone afnetworking phasset

目前,我使用以下代码将文件上传到服务器

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"]);

    }];
}

此方法适用于模拟器,但在真实设备上失败:空文件很可能由于无法从本地存储读取而上载到服务器。 日志显示通知

  

注意:Sandbox:MyApp(213)拒绝文件读取数据   /private/var/mobile/Media/DCIM/101APPLE/IMG_1570.PNG

我相信此笔记意味着应用无法按指定路径访问该文件。 此外,我还尝试了一种替代方法,通过附加NSData来上传文件,NSData是从请求PHAsset数据返回的。但是这种方法在大型媒体文件的情况下是不可用的。因为整个文件都被加载到内存中。

有什么想法吗?

2 个答案:

答案 0 :(得分:5)

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

根据我的经验,尝试直接从PHAsset资源网址上传将失败。 Apple似乎没有授予我们从PHAsset源文件直接上传所需的权限。请参阅论坛帖子here。这是一种痛苦,因为如果我们想要上传视频,它会迫使我们使用大量的额外磁盘空间。

要获取您要上传的视频文件的本地文件网址,您需要使用以下任意一种:

requestExportSessionForVideo(_:options:exportPreset:resultHandler:)

requestAVAssetForVideo(_:options:resultHandler:)

您将使用这些方法将视频文件的副本导出到您控制的磁盘上的位置。并从该文件上传。奖励功能:如有必要,这两种方法都将从iCloud下载文件。

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

即使您没有上传到Vimeo服务器,也可以使用VimeoUpload中包含的PHAssetExportSessionOperationExportOperation类来完成您要执行的操作。有关obtaining a file url for a PHAsset的详细信息,请参阅repo README。它还包括obtaining a file url for an ALAsset的工具。

如果您对使用PHAssetExportSessionOperationExportOperation不感兴趣,请查看其实施内容,了解有关如何使用Apple类的详细信息。

答案 1 :(得分:3)

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

对于视频,您应该使用适当的方法requestExportSessionForVideorequestAVAssetForVideo 如果您可以将部署目标限制为iOS 9,那么您还应该看看PHAssetResourceManager

的方法