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

FileSystem.getInfoAsync on IOS throw error "ph://...' isn't readable" #4995

Closed
AramArakelyan22 opened this issue Jul 18, 2019 · 15 comments · Fixed by #5195
Closed

FileSystem.getInfoAsync on IOS throw error "ph://...' isn't readable" #4995

AramArakelyan22 opened this issue Jul 18, 2019 · 15 comments · Fixed by #5195

Comments

@AramArakelyan22
Copy link

Environment:
OS: IOS 10.14.4,
Node: 10.15.3,
npm: 6.4.1

Packages:
expo: 33.0.0,
react: 16.8.3,
react-native: https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz

Device:
iphone Xr, IOS 12.2

Steps to Reproduce
code:

try {
FileSystem.getInfoAsync(url);
} catch(e) {
console.log(error.message);
}

output: File 'ph://1724924E-9632-492E-B4E1-8DB6C818FF5B/L0/001' isn't readable.
permissions CAMERA_ROLL granted.
It reproduce only on IOS, on Android it works fine.

How can i solve this problem?

@AramArakelyan22 AramArakelyan22 changed the title FileSystem.getInfoAsync on IOS throw error "File 'file://...' isn't readable." FileSystem.getInfoAsync on IOS throw error "ph://...' isn't readable" Jul 18, 2019
@cruzach
Copy link
Contributor

cruzach commented Jul 18, 2019

Hey @AramArakelyan22 - could you provide a snack that reproduces this issue?

@bluedaniel
Copy link

bluedaniel commented Jul 18, 2019

Hey @cruzach

I'm also having this issue, here is a snack that reproduces it.

https://snack.expo.io/By5ImfRZH

Ultimately I'm trying to convert the image to Base64.

@cruzach
Copy link
Contributor

cruzach commented Jul 18, 2019

Hm..I just tested that snack on my iPhone 7 and it worked without any problems. What device are you using to test?

@bluedaniel
Copy link

An iPad Pro, the simulator and device.

Are you sure it works? In the demo, when you click on an image then FileSystem will error. It shows that way in the online snack I posted above

@cruzach
Copy link
Contributor

cruzach commented Jul 18, 2019

Oops, sorry I made a mistake. You're right, I'm getting the same error

@brian1959
Copy link

Any ideas how to fix this? I am using SDK33 and having the same problem.

@Sford4
Copy link

Sford4 commented Jul 24, 2019

Same problem, SDK 33, please let me know if we find a solution!

@allankikkas
Copy link

Still broken in SDK 34

@cruzach cruzach added the iOS label Jul 31, 2019
@allankikkas
Copy link

This also happens in published builds in testflight, not just in simulator.

sjchmiela added a commit that referenced this issue Aug 6, 2019
# Why

Should fix #4995.

# How

Added support for `ph://` scheme in FileSystem.

# Test Plan

With this change running
```js
CameraRoll.getPhotos({
    first: 10,
    assetType: 'All',
  }).then(({ edges }) => FileSystem.getInfoAsync(edges[0].node.image.uri).then(console.log));
```
rendered
```
Object {
  "exists": true,
  "isDirectory": false,
  "modificationTime": 1526314683.382386,
  "uri": null,
}
```
instead of
```
[Unhandled promise rejection: Error: File 'ph://4607021A-7369-459C-881D-277E6612A4E7/L0/001' isn't readable.]
```
sjchmiela added a commit that referenced this issue Aug 6, 2019
# Why

Should fix #4995.

# How

Added support for `ph://` scheme in FileSystem.

# Test Plan

With this change running
```js
CameraRoll.getPhotos({
    first: 10,
    assetType: 'All',
  }).then(({ edges }) => FileSystem.getInfoAsync(edges[0].node.image.uri).then(console.log));
```
rendered
```
Object {
  "exists": true,
  "isDirectory": false,
  "modificationTime": 1526314683.382386,
  "uri": null,
}
```
instead of
```
[Unhandled promise rejection: Error: File 'ph://4607021A-7369-459C-881D-277E6612A4E7/L0/001' isn't readable.]
```
@allankikkas
Copy link

@sjchmiela does it make camera roll files accessible using Filesystem. readAsStringAsync ? Also documentation probably should be updated regarding receiving null in uri, not inputted uri as stated in docs.

@peterkuiper
Copy link

peterkuiper commented Sep 11, 2019

@sjchmiela I know this issue is closed, but how can we get this fix? I have tried patching expo-file-system (in node_modules) manually but it still doesn't work so I'm not sure where this patch needs to be applied. It does work, I just made a mistake with an import. I'm also curious where files like these ios/versioned-react-native/ABI34_0_0/EXFileSystem/ABI34_0_0EXFileSystem/ABI34_0_0EXFileSystem.m end up.

For those running into this issue, I have added instructions on how to patch expo-file-system until a new version is released:

mkdir patches

cat << EOF >> patches/expo-file-system.patch
diff -Naur node_modules.orig/expo-file-system/ios/EXFileSystem/EXFileSystem.m node_modules/expo-file-system/ios/EXFileSystem/EXFileSystem.m
--- node_modules.orig/expo-file-system/ios/EXFileSystem/EXFileSystem.m	2019-09-10 17:08:56.000000000 +0200
+++ node_modules/expo-file-system/ios/EXFileSystem/EXFileSystem.m	2019-09-10 17:10:27.000000000 +0200
@@ -194,7 +194,7 @@

   if ([uri.scheme isEqualToString:@"file"]) {
     [EXFileSystemLocalFileHandler getInfoForFile:uri withOptions:options resolver:resolve rejecter:reject];
-  } else if ([uri.scheme isEqualToString:@"assets-library"]) {
+  } else if ([uri.scheme isEqualToString:@"assets-library"] || [uri.scheme isEqualToString:@"ph"]) {
     [EXFileSystemAssetLibraryHandler getInfoForFile:uri withOptions:options resolver:resolve rejecter:reject];
   } else {
     reject(@"E_FILESYSTEM_INVALID_URI",
@@ -453,7 +453,7 @@

   if ([from.scheme isEqualToString:@"file"]) {
     [EXFileSystemLocalFileHandler copyFrom:from to:to resolver:resolve rejecter:reject];
-  } else if ([from.scheme isEqualToString:@"assets-library"]) {
+  } else if ([from.scheme isEqualToString:@"assets-library"] || [from.scheme isEqualToString:@"ph"]) {
     [EXFileSystemAssetLibraryHandler copyFrom:from to:to resolver:resolve rejecter:reject];
   } else {
     reject(@"E_FILESYSTEM_INVALID_URI",
@@ -787,6 +787,7 @@
                             @"assets-library",
                             @"http",
                             @"https",
+                            @"ph",
                             ];
   if ([validSchemas containsObject:uri.scheme]) {
     return UMFileSystemPermissionRead;
diff -Naur node_modules.orig/expo-file-system/ios/EXFileSystem/EXFileSystemAssetLibraryHandler.m node_modules/expo-file-system/ios/EXFileSystem/EXFileSystemAssetLibraryHandler.m
--- node_modules.orig/expo-file-system/ios/EXFileSystem/EXFileSystemAssetLibraryHandler.m	2019-09-10 17:08:56.000000000 +0200
+++ node_modules/expo-file-system/ios/EXFileSystem/EXFileSystemAssetLibraryHandler.m	2019-09-10 17:11:03.000000000 +0200
@@ -10,7 +10,12 @@
               resolver:(UMPromiseResolveBlock)resolve
               rejecter:(UMPromiseRejectBlock)reject
 {
-  PHFetchResult<PHAsset *> *fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[fileUri] options:nil];
+  NSError *error;
+  PHFetchResult<PHAsset *> *fetchResult = [self fetchResultForUri:fileUri error:&error];
+  if (error) {
+    reject(@"E_UNSUPPORTED_ARG", error.description, error);
+    return;
+  }
   if (fetchResult.count > 0) {
     PHAsset *asset = fetchResult[0];
     NSMutableDictionary *result = [NSMutableDictionary dictionary];
@@ -52,8 +57,13 @@
       return;
     }
   }
-
-  PHFetchResult<PHAsset *> *fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[from] options:nil];
+
+  PHFetchResult<PHAsset *> *fetchResult = [self fetchResultForUri:from error:&error];
+  if (error) {
+    reject(@"E_UNSUPPORTED_ARG", error.description, error);
+    return;
+  }
+
   if (fetchResult.count > 0) {
     PHAsset *asset = fetchResult[0];
     [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
@@ -72,4 +82,24 @@
   }
 }

+// adapted from RCTImageLoader.m
++ (PHFetchResult<PHAsset *> *)fetchResultForUri:(NSURL *)url error:(NSError **)error
+{
+  if ([url.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame) {
+    // Fetch assets using PHAsset localIdentifier (recommended)
+    NSString *const localIdentifier = [url.absoluteString substringFromIndex:@"ph://".length];
+    return [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
+  } else if ([url.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
+    // This is the older, deprecated way of fetching assets from assets-library
+    // using the "assets-library://" protocol
+    return [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
+  }
+
+  NSString *description = [NSString stringWithFormat:@"Invalid URL provided, expected scheme to be either 'ph' or 'assets-library', was '%@'.", url.scheme];
+  *error = [[NSError alloc] initWithDomain:NSURLErrorDomain
+                                      code:NSURLErrorUnsupportedURL
+                                  userInfo:@{NSLocalizedDescriptionKey: description}];
+  return nil;
+}
+
 @end
EOF

patch -p0 < patches/expo-file-system.patch

@sjchmiela
Copy link
Contributor

ABIXX_X_X files are Expo client-specific files allowing you to run experiences in multiple SDK versions side by side. To patch EXFilesystem, you'd need to edit node_modules/expo-file-system/ios/EXFileSystem/… files according to this and this diff. 🙂

@MahmoudMH
Copy link

ABIXX_X_X files are Expo client-specific files allowing you to run experiences in multiple SDK versions side by side. To patch EXFilesystem, you'd need to edit node_modules/expo-file-system/ios/EXFileSystem/… files according to this and this diff. 🙂

I made these changes but still the same error.

@sjchmiela
Copy link
Contributor

Did you do them on an ejected project? Since these are in native code, you'll need to edit native code, i. e. also rebuild native code (or wait for native code update coming with SDK35-compatible Expo client).

@MahmoudMH
Copy link

I did not, I was trying to edit on node_modules directly and rebuild the bundle.
I will try to make it once I eject Expo.

Thanks @sjchmiela

@lock lock bot added the outdated label Mar 17, 2020
@lock lock bot locked and limited conversation to collaborators Mar 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants