PHAsset + AFNetworking。无法在真机上上传文件到服务器

Posted

技术标签:

【中文标题】PHAsset + AFNetworking。无法在真机上上传文件到服务器【英文标题】:PHAsset + AFNetworking. Unable to upload files to the server on a real device 【发布时间】:2015-10-06 03:59:18 【问题描述】:

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

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

    ];

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

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

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

有什么想法吗?

【问题讨论】:

【参考方案1】:

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

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

为了获取您打算上传的视频文件的本地文件 url,您需要使用:

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 类的详细信息。

【讨论】:

【参考方案2】:

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

对于视频,您应该使用适当的方法 requestExportSessionForVideorequestAVAssetForVideo 如果你可以将你的部署目标限制在 ios 9,你也应该看看PHAssetResourceManager的方法

【讨论】:

以上是关于PHAsset + AFNetworking。无法在真机上上传文件到服务器的主要内容,如果未能解决你的问题,请参考以下文章

PHAsset 无法获取

我无法使用 RNFS 使用从 RNCameraRoll 获取的 phasset 读取文件

如何获取视频 PHAsset 磁盘文件大小?

如何将 PHAsset 存储到核心数据中

如何从 PHAsset 提取中获取照片?

从 PHAsset 获取视频时如何检测视频是不是为横向/纵向?