The File "Xxx.Mp4" Couldn't Be Opened Because You Don't Have Permission to View It

The file couldn’t be opened because you don’t have permission to view it (REAL DEVICE)

In case someone is interested, I've been able to solve it by calling url.startAccessingSecurityScopedResource() in the document picker before actually accessing the file. Hope this helps!

Swift - The file couldn’t be opened because you don’t have permission to view it

The problem there is that the file path will change every time you run the app. You shouldn't save the whole file path. You can save its name and reconstruct your URL before loading it.

File couldn’t be opened because you don’t have permission to view it error

Anyone coming across this thread, @LeoDabus pointed me to where to turn off sandbox, which worked:

Sample Image

He also cleaned up my code a bit:

let fileURL = URL( fileURLWithPath: "/Users/me/file.txt" )    
var rawDataString: String
var errorString: String?

do {
rawDataString = try String( contentsOf: fileURL, encoding: .utf8 )
} catch let error as NSError {
errorString = error.description
rawDataString = ""
return
}

Catch Error Reading File From Disk - You Don't Have Permissions

I'm less knowledgeable about exactly how this works on iOS, but I do have some knowledge about how it works for macOS, and the two should be similar. For macOS sandboxed apps the user has to select the file outside of the sandbox specifically via NSOpenPanel or NSSavePanel. The equivalent on iOS would be UIDocumentPickerViewController, but I assume an explicit share would work too. Based on that, here's how I would think about it and what I would try, if I were faced with your problem:

You've got two URLs involved in your call to FileManager.default.copy(). It's not clear which one is producing the error, so I'll consider both.

First let's look at fileURL. You're constructing it to put a file in the user's Documents directory. On macOS at least, that directory is not in the app's sandbox, which means asking the user via NSSavePanel (which also means they might decide to put it somewhere else). You might have to do the UIKit equivalent, or just make sure you're picking a location that is in your sandbox.

To test that, instead of doing the copy, try writing to fileURL to isolate just that one. For example:

do { try "TestString".data(using: .utf8)?.write(url: fileURL) }
catch { print("Write failed: \(error.localizedDescription)") }

If that fails, then your problem is with fileURL, in which case you may need to use UIDocumentPickerViewController to save it, or pick a location that's definitely in the app's sandbox.

If the test succeeds, the problem must be with the incoming URL.

I'm going to assume that url is already security scoped, because I'm not sure how sharing would even work otherwise. What I think is most likely happening behind the scenes is that when the user shares a URL with your app, iOS creates a security-scoped bookmark from the URL and sends the bookmark rather than the URL to your app. Then on your app's end, that bookmark is used to reconstitute the URL before passing it on to your app's delegate. If I'm right about that you'll need to open and close a security scope to use it:

url.startAccessingSecurityScopedResource()

// access your file here

url.stopAccessingSecurityScopedResource()

Note that stopAccessingSecurityScopeResource() has to be called on the main thread, so if you're code is happening asynchronously you'll need to schedule it to run there:

url.startAccessingSecurityScopedResource()

// access your file here

DispatchQueue.main.async { url.stopAccessingSecurityScopedResource() }

If you need to save the URL itself to use in a future run of your program... you can't. Well, you can, but it won't be valid, so you'll be right back to permissions errors. Instead you have to save a bookmark, and then in that future run, reconstruct the URL from the bookmark.

let bookmark = try url.bookmarkData(
options: .withSecurityScope,
includingResourceValuesForKeys: nil,
relativeTo: nil
)

bookmark is an instance of Data, so you can write that to UserDefaults or wherever you might want to save it. To get a URL back from it later:

var isStale = false
let url = try URL(
resolvingBookmarkData: bookmark,
options: .withSecurityScope,
relativeTo: nil,
bookmarkDataIsStale: &isStale
)

if isStale
{
let newBookmark = try url.bookmarkData(
options: .withSecurityScope,
includingResourceValuesForKeys: nil,
relativeTo: nil
)
// Save the new bookmark
}

Note that if isStale is true after the initializer returns, then you need to remake and resave the bookmark.

It's a shame that we have to go through this much trouble, but we live in a world where some people insist on doing bad things to other people's devices and data, so it's what we have to deal with the protect users from malicious data breaches.

My swift app needs access to photo library. I've set access, but still get an error

Did you request authorization?

PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
switch status {
case .notDetermined:
// The user hasn't determined this app's access.
case .restricted:
// The system restricted this app's access.
case .denied:
// The user explicitly denied this app's access.
case .authorized:
// The user authorized this app to access Photos data.
case .limited:
// The user authorized this app for limited Photos access.
@unknown default:
fatalError()
}
}


Related Topics



Leave a reply



Submit