Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Path Issue in iOS 13.1 #346

Open
3 tasks done
GriffinLedingham opened this issue Sep 11, 2019 · 31 comments
Open
3 tasks done

File Path Issue in iOS 13.1 #346

GriffinLedingham opened this issue Sep 11, 2019 · 31 comments

Comments

@GriffinLedingham
Copy link

GriffinLedingham commented Sep 11, 2019

Bug Report

Problem: Local file path returns incorrectly on iOS 13.1

What is expected to happen?

cordova.file.applicationDirectory returns a file path which is supported by resolveLocalFileSystemURL to parse out a local path path for use in a cordova app.

What does actually happen?

cordova.file.applicationDirectory now returns a file path prefixed with /private/ which is incorrectly parsed by resolveLocalFileSystemURL to produce an incorrect file path for use in a cordova app.

Information

This issue exists is the iOS 13.1 beta, which is due to release at the end of September. Being this early in a beta, it's difficult to determine whether iOS is broken, or the plugin is broken, but to be proactive I am assuming the latter.

I've dug through the 13.1 release notes, and don't see anything jumping out at me that'd modify the local file storage directory paths. With recent changes to the HTML5 app guidelines over the Summer, I figure this could be a rogue change of sorts to modify how apps are being sandboxed/given access to the file system.

Testing to reproduce this, I was building my iOS app to two physical iPhone XR's, one on iOS 13 Gold Master, and one on iOS 13.1 Beta 3 and comparing file paths returned by the plugin.

Command or Code

cordova.file.applicationDirectory
window.resolveLocalFileSystemURL

Environment, Platform, Device

iPhone XR iOS 13.1 Beta 3

Version information

cordova-plugin-file 6.0.2

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@boredom2
Copy link

Hi there,

this Problem also occurs on iOS 13 "Live Version", so its not Beta-related.
On iOS 13, selecting a File (Video, in our Case), leads to a Path similar to:

"file:///private/var/mobile/Containers/Data/PluginKitPlugin/D61F8E95-612D-4CB3-94BB-26ADDF68F26A/tmp/trim.76E14050-7A9F-430F-B13F-1A8758033345.MOV"

which breaks window.resolveLovalFileURL with FileError 1.

This happens on any physical Devices, we tested it so far - but for some Reasons, does not happen in an emulated Device in XCode.

A Fix for iOS13 or a Hint, how to work around this, would be really helfull.

Thanks,
Christoph

@GriffinLedingham GriffinLedingham changed the title File Path Issue in iOS 13.1 Beta 3 File Path Issue in iOS 13.1 Sep 24, 2019
@GriffinLedingham
Copy link
Author

I’m wondering if this could be related to the sandbox security issue fixed in 13.1.1. Will investigate tomorrow and report back if 13.1.1 seems to fix this.

https://support.apple.com/en-ca/HT210624

@boredom2
Copy link

13.1.1 is not fixing this - sadly...

@GriffinLedingham
Copy link
Author

Yeah, tested this morning on my case as well and 13.1.1 did not help the matter.

@RidClick
Copy link

I have the same problem, has anyone managed to make it work on iOS 13?

@rizz360
Copy link

rizz360 commented Oct 1, 2019

iOS & iPad OS 13.1.2 were released a few hours ago.

Will test and report back...

Edit: I no longer receive paths starting with /private/ and my app is working again.
So this seems to be fixed in 13.1.2!

@boredom2
Copy link

boredom2 commented Oct 1, 2019

Sadly, the Issue is not fixed in 13.1.2 - at least not for Videos, which we have Focus on.
Selecting a Video from the Picker still leads to something like "file:///private/var/mobile/Containers/Data/PluginKitPlugin/097EF2B0-8AAE-4137-A1E8-ECE3EDFD3B01/tmp/trim.2D02472E-C28C-4DB6-8EBF-C220337544FC.MOV" which leads to Error Code 1. So from our Point of view, the Issue is still there :(

@RidClick
Copy link

RidClick commented Oct 1, 2019

iOS & iPad OS 13.1.2 were released a few hours ago.

Will test and report back...

Edit: I no longer receive paths starting with /private/ and my app is working again.
So this seems to be fixed in 13.1.2!

Do you copy the temporary image to the cordova.file.applicationDirectory directory?
Because I am copying the image to the directory and then showing it, in ios 10.X or 12.X it works but in 13.1.2 it still does not work.

@rizz360
Copy link

rizz360 commented Oct 1, 2019

iOS & iPad OS 13.1.2 were released a few hours ago.

Will test and report back...

Edit: I no longer receive paths starting with /private/ and my app is working again.
So this seems to be fixed in 13.1.2!

Sorry I have to correct myself. A bug in my debug build acted as a workaround...it's still broken.
private/ is no longer included in DirectoryEntry.fullPath - but fullPath is still way too long.

Instead of having something like www/assets/data/... in full path, it now contains var/containers/Bundle/Application/EF.........FE02/APPNAME.app/www/assets/data/... which is nearly the full nativeURL - only missing file:///.

@GriffinLedingham
Copy link
Author

Still seeing the issue on our end with 13.1.2 unfortunately.

@kkabell
Copy link

kkabell commented Oct 2, 2019

This is probably not a lasting solution, but I managed to restore functionality for uploading videos from the photo library in my app, so I guess that's good :)

The problem is in cordova-plugin-camera:
It seems that the path is actually correct, but that the url simply gets invalidated too soon, causing the file manager to not be able to find the file. The workaround is to keep a reference to the info object passed to the imagePickerController:didFinishPickingMediaWithInfo: method of the UIImagePickerControllerDelegate, and thus preventing the url from being invalidated.

This is what worked for me:
https://github.com/kkabell/cordova-plugin-camera/commit/b1b0c9499b6b5c18d109671967e1218e05428e0a

@RidClick
Copy link

RidClick commented Oct 3, 2019

This is probably not a lasting solution, but I managed to restore functionality for uploading videos from the photo library in my app, so I guess that's good :)

The problem is in cordova-plugin-camera:
It seems that the path is actually correct, but that the url simply gets invalidated too soon, causing the file manager to not be able to find the file. The workaround is to keep a reference to the info object passed to the imagePickerController:didFinishPickingMediaWithInfo: method of the UIImagePickerControllerDelegate, and thus preventing the url from being invalidated.

This is what worked for me:
kkabell/cordova-plugin-camera@b1b0c94

I have added the lines of your code to the camera plugin, removed and re-added the iOS platform and compiled, it is true that the path of the photo seems correct, but it still does not show the photo that I copied and pasted in the cordova.file.applicationDirectory in iOS 13.1.2

@DanielLeberle
Copy link

Please have a look at this issue in cordova-plugin-camera:
apache/cordova-plugin-camera#506

The fix provided in this comment worked for us!

@JianhuisHuang
Copy link

Sadly, the Issue is not fixed in 13.1.2 - at least not for Videos, which we have Focus on.
Selecting a Video from the Picker still leads to something like "file:///private/var/mobile/Containers/Data/PluginKitPlugin/097EF2B0-8AAE-4137-A1E8-ECE3EDFD3B01/tmp/trim.2D02472E-C28C-4DB6-8EBF-C220337544FC.MOV" which leads to Error Code 1. So from our Point of view, the Issue is still there :(


I have the same issue, are you fixed or found solution?Thanks. @boredom2

@adamjpeterson
Copy link

Am am having this save issue in 13.1.2. Would be grateful to anyone who finds a solution to accessing resolveLocalFileSystemURL when selecting a video from the gallery.

@tmk1991
Copy link

tmk1991 commented Oct 19, 2019

@DanielFreiburger

I applied that fix and it didn't work. I keep getting an ENCODING_ERR when calling readAsArrayBuffer

As mentioned below. the file oddly still has this weird prefix trim.0932D2E4-2811-49EF-8D12-6FA86EFDCA34.MOV
apache/cordova-plugin-camera#506 (comment)

@kkabel 's fix is confirmed working!

tmk1991 added a commit to TDTECHLINK/cordova-plugin-camera that referenced this issue Oct 19, 2019
@benmcmaster
Copy link

@kkabell it seems like it's working and resolveLocalFileSystemURL returns a url. However, when I try to load that url using the <video> tag I get and error:

[Error] Not allowed to load local resource: file:////var/mobile/Containers/Data/PluginKitPlugin/xxxxxxx/tmp/trim.zzzzzz.MOV

Any ideas?

@breautek
Copy link
Contributor

breautek commented Oct 29, 2019

@kkabell it seems like it's working and resolveLocalFileSystemURL returns a url. However, when I try to load that url using the <video> tag I get and error:

[Error] Not allowed to load local resource: file:////var/mobile/Containers/Data/PluginKitPlugin/xxxxxxx/tmp/trim.zzzzzz.MOV

Any ideas?

Sounds like you're CSP is not setup properly. I've provided some references below.

https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-whitelist/#content-security-policy
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/media-src

You need to allow the file: protocol, by having file: in the appropriate directive.

@benmcmaster
Copy link

@breautek Thanks! my CSP was fine... I had also upgraded my webview to cordova-plugin-ionic-webview which required me to use window.Ionic.WebView.convertFileSrc() to get the proper url for local files.

@sudarshanadayananda
Copy link

This is probably not a lasting solution, but I managed to restore functionality for uploading videos from the photo library in my app, so I guess that's good :)

The problem is in cordova-plugin-camera:
It seems that the path is actually correct, but that the url simply gets invalidated too soon, causing the file manager to not be able to find the file. The workaround is to keep a reference to the info object passed to the imagePickerController:didFinishPickingMediaWithInfo: method of the UIImagePickerControllerDelegate, and thus preventing the url from being invalidated.

This is what worked for me:
kkabell/cordova-plugin-camera@b1b0c94

you save my day dude. thanks a lot.

@08Thug
Copy link

08Thug commented Jan 29, 2020

Well the problem is with the apache cordova camera plugin it provides the temporary path to the video file to come out from this error implement below changes in camera plugin.

in CDVCamera.m change THIS:

(CDVPluginResult*)resultForVideo:(NSDictionary*)info
{
NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:filePath];
}

to THIS:

(CDVPluginResult*)resultForVideo:(NSDictionary*)info
{
NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];

NSArray* spliteArray = [moviePath componentsSeparatedByString: @"/"];
NSString* lastString = [spliteArray lastObject];
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp"];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:lastString];
[fileManager copyItemAtPath:moviePath toPath:filePath error:&error];

return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:filePath];
}

Hope it will help you.

And ofcourse you should perform this also

 if (this.platform.is('android')) {
    filePath = 'file:///' + this.uploadForm.controls['file'].value;
  } else {
    filePath = this.uploadForm.controls['file'].value;
  }

@wingo7
Copy link

wingo7 commented Jan 31, 2020

This is probably not a lasting solution, but I managed to restore functionality for uploading videos from the photo library in my app, so I guess that's good :)

The problem is in cordova-plugin-camera:
It seems that the path is actually correct, but that the url simply gets invalidated too soon, causing the file manager to not be able to find the file. The workaround is to keep a reference to the info object passed to the imagePickerController:didFinishPickingMediaWithInfo: method of the UIImagePickerControllerDelegate, and thus preventing the url from being invalidated.

This is what worked for me:
kkabell/cordova-plugin-camera@b1b0c94

Unfortunately, doesn't work for me ;(

@crapthings
Copy link

iphone6s 12.0 same here

works on simulator, but not real device

@nvahalik
Copy link

I recently updated my copy of cordova-plugin-camera to use a branch that includes apache/cordova-plugin-camera@bfa38fe and this issue has been resolved for me.

@inu-web
Copy link

inu-web commented Nov 5, 2020

Maybe this may help anybody who struggles with this too ... we had the exact same effect
window.resolveLocalFileSystemURL(cordova.file.applicationDirectory ) always faild with FileError 5 (ENCODING_ERROR)
on real device (iPadAir 4th Gen) -> Always File Error 5
But it worked on The iPadAir Simulator(4.th Gen) without problems ...

after hours and hours bangign our heads against all walls in the office
We were able to resolve this by: "not using es6" in the callback for success --- the good old way works on Simulator & Device
CONST filePath = cordova.file.applicationDirectory + "www/" window.resolveLocalFileSystemURL(filePath , function(fileEntry){ ... });
hope this helps

@BanTheRewind
Copy link

BanTheRewind commented Dec 21, 2020

I resolved this by using the application storage on iOS, rather than the "data directory".

function getDataDirectory() {
    if (device.platform == "iOS") {
        return `${cordova.file.applicationStorageDirectory}Documents`;
    }
    return `${cordova.file.dataDirectory}`;
}

...

window.resolveLocalFileSystemURL(getDataDirectory(), (directoryEntry) => {
  // Enjoy cross-platform success here
}

@itrafimovich
Copy link

itrafimovich commented Feb 12, 2021

I've solved the same problem in other environment

It’s look like iOS bug (detected only in Swift code)
path=file:///private/var/mobile/Containers/Shared/AppGroup/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXX/folder/

let result = fileManager.fileExists(atPath: path, isDirectory: &isDirectory) // false
let result = fileManager.fileExists(atPath: path.absoluteURL.path, isDirectory: &isDirectory) // true

Using path.absoluteURL.path without prefix 'file://'
path.absoluteURL.path=/private/var/mobile/Containers/Shared/AppGroup/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXX/folder/

Hope it will help

@codal-shubhamb
Copy link

codal-shubhamb commented Aug 5, 2021

Maybe it is not the issue of file plugin, It seems like it is issue of Cordova-camera plugin.

I have solved this issue just by removing and adding camera plugin in my application, You should try this too. The changes in Cordova-camera plugin which solves the issue are as following:
Filename - https://github.com/apache/cordova-plugin-camera/blob/master/src/ios/CDVCamera.m and just search "ResultForVideo" and there are these three lines are added in latest plugin
// On iOS 13 the movie path becomes inaccessible, create and return a copy
if (IsAtLeastiOSVersion(@"13.0")) {
moviePath = [self createTmpVideo:[[info objectForKey:UIImagePickerControllerMediaURL] path]];
}

@huyewen
Copy link

huyewen commented Sep 9, 2021

This is probably not a lasting solution, but I managed to restore functionality for uploading videos from the photo library in my app, so I guess that's good :)

The problem is in cordova-plugin-camera:
It seems that the path is actually correct, but that the url simply gets invalidated too soon, causing the file manager to not be able to find the file. The workaround is to keep a reference to the info object passed to the imagePickerController:didFinishPickingMediaWithInfo: method of the UIImagePickerControllerDelegate, and thus preventing the url from being invalidated.

This is what worked for me:
kkabell/cordova-plugin-camera@b1b0c94

Wow, so cool, my issue finally is solved because of your reply what you give here, thank you very much.

@aehlke
Copy link

aehlke commented Jul 20, 2023

maybe adjacently useful code, borrowed from thebaselab/codeapp which uses this logic to cover the /private/ issue in another context

fileprivate func getRootDirectory() -> URL {
    // We want ./private prefix because all other files have it
    if let documentsPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        .first
    {
        #if targetEnvironment(simulator)
            return documentsPathURL
        #else
            if let standardURL = URL(
                string: documentsPathURL.absoluteString.replacingOccurrences(
                    of: "file:///", with: "file:///private/"))
            {
                return standardURL
            } else {
                return documentsPathURL
            }
        #endif
    } else {
        fatalError("Could not locate Document Directory")
    }
}

@MustakTalukder
Copy link

Hi All,
Go to your Xcode, And follow this comment, just replace the code. It works for me.

  • Go to your Xcode
  • Search for "(CDVPluginResult*)resultForVideo:(NSDictionary*)info" in your XCode project
  • Replace the code according to the instructions provided in this comment : LINK
  • I have attached a photo to show you how I did it.
  • photo
    Screenshot 2024-04-01 at 6 04 36 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests