Grigoriy Uskov
Grigoriy Uskov

Reputation: 152

File Provider Extension, importDocumentAtURL:: can't read file at given URL (iOS 11.4.1)

I'm having troubles with Paste opertaions into my containers in File Provider extension.

If I paste copied image or text into Files app -> My App -> any folder the file at fileURL can not be read (as a result can't be uploaded to my servers nor stored locally).

- (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;

    ...

Both readErrorMessage and copyErrorMessage are:

The file “text.txt” couldn’t be opened because you don’t have permission to view it.

What am I doing wrong here?

Thanks.

UPD: This happens to any file copied from my container, iCloud container, as well as synthetic files produced from text/image/other data from system Clipboard.

Upvotes: 0

Views: 902

Answers (1)

trungduc
trungduc

Reputation: 12144

Looks like you are working on a security-scoped URL.

According to Document Picker Programming Guide

Any app that accesses documents outside its sandbox must meet the following requirements:

  • Your app must perform all file read and write operations using file coordination.

  • If you display the contents of the document to the user, you must track the document’s state using a file presenter. If you’re only showing a list of files, a file presenter is not necessary.

  • Do not save any URLs accessed through open or move operations. Always open the document using a document picker, a metadata query, or a security-scoped bookmark to the URL.

  • These operations return security-scoped URLs. You must call startAccessingSecurityScopedResource before accessing the URL.

  • If startAccessingSecurityScopedResource returns YES, call stopAccessingSecurityScopedResource when you are done using the file.

  • If you are using a UIDocument subclass, it will automatically consume the security-scoped URLs for you. There’s no need to call startAccessingSecurityScopedResource or stopAccessingSecurityScopedResource. UIDocument also acts as a file presenter and automatically handles file coordination. For these reasons, using a UIDocument subclass is highly recommended for all files outside your app’s sandbox.

So you need to call startAccessingSecurityScopedResource before the file at this url is copied. Your code may become.

- (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];
}

Upvotes: 2

Related Questions