文件提供商扩展程序importDocumentAtURL ::无法读取给定URL(iOS 11.4.1)上的文件

时间:2018-09-06 07:30:16

标签: ios objective-c fileprovider-extension

我在File Provider扩展程序中无法将粘贴操作粘贴到我的容器中。

如果我将复制的图像或文本粘贴到“文件”应用程序->“我的应用程序”->任何文件夹中,则无法读取fileURL上的文件(结果是无法将其上传到我的服务器或本地存储)。

- (void)importDocumentAtURL:(NSURL *)fileURL
     toParentItemIdentifier:(NSFileProviderItemIdentifier)parentItemIdentifier
          completionHandler:(void (^)(NSFileProviderItem _Nullable importedDocumentItem, NSError * _Nullable error))completionHandler
{

    NSError *readError = nil;
    NSData *fileData = [NSData dataWithContentsOfURL:fileURL options:NSDataReadingMappedAlways error:&readError];
    NSString *readErrorMessage = readError.localizedDescription;

    NSURL *myFileURL = [NSFileProviderManager.defaultManager.documentStorageURL URLByAppendingPathComponent:@"temp.dat"];
    NSError *copyError = nil;
    BOOL copyResult = [_fileManager copyItemAtURL:fileURL toURL:myFileURL error:&copyError];
    NSString *copyErrorMessage = copyError.localizedDescription;

    ...

readErrorMessage和copyErrorMessage都是:

由于您没有查看权限,因此无法打开文件“ text.txt”。

我在这里做什么错了?

谢谢。

UPD::从我的容器,iCloud容器复制的任何文件,以及从系统剪贴板的文本/图像/其他数据生成的合成文件都将发生这种情况。

1 个答案:

答案 0 :(得分:1)

好像您正在使用安全范围内的URL。

根据Document Picker Programming Guide

  

任何访问其沙箱外部文档的应用都必须满足以下要求:

     
      
  • 您的应用必须使用文件协调功能执行所有文件读取和写入操作。

  •   
  • 如果向用户显示文档的内容,则必须使用文件演示器跟踪文档的状态。如果您仅显示文件列表,则不需要文件演示者。

  •   
  • 请勿保存通过打开或移动操作访问的任何URL。始终使用文档选择器,元数据查询或URL的安全范围书签来打开文档。

  •   
  • 这些操作返回安全范围内的URL。您必须先致电startAccessingSecurityScopedResource才能访问URL。
  •   
  • 如果startAccessingSecurityScopedResource返回是,请在使用完文件后调用stopAccessingSecurityScopedResource
  •   
  • 如果您使用的是UIDocument子类,它将自动为您使用安全范围的URL。无需致电startAccessingSecurityScopedResourcestopAccessingSecurityScopedResource。 UIDocument还充当文件演示者,并自动处理文件协调。由于这些原因,强烈建议对应用程序沙箱之外的所有文件使用UIDocument子类。
  •   

因此,您需要在复制此URL上的文件之前调用startAccessingSecurityScopedResource。您的代码可能会变成

- (void)importDocumentAtURL:(NSURL *)fileURL
     toParentItemIdentifier:(NSFileProviderItemIdentifier)parentItemIdentifier
          completionHandler:(void (^)(NSFileProviderItem _Nullable importedDocumentItem, NSError * _Nullable error))completionHandler
{

  NSError *readError = nil;
  NSData *fileData = [NSData dataWithContentsOfURL:fileURL options:NSDataReadingMappedAlways error:&readError];
  NSString *readErrorMessage = readError.localizedDescription;

  NSURL *myFileURL = [NSFileProviderManager.defaultManager.documentStorageURL URLByAppendingPathComponent:@"temp.dat"];

  // Call |startAccessingSecurityScopedResource| before working on the url
  [fileURL startAccessingSecurityScopedResource];

  NSError *copyError = nil;
  BOOL copyResult = [_fileManager copyItemAtURL:fileURL toURL:myFileURL error:&copyError];
  NSString *copyErrorMessage = copyError.localizedDescription;

  // ....
  // Call |stopAccessingSecurityScopedResource| after everything is done.
  [fileURL stopAccessingSecurityScopedResource];
}