React Native iOS read image from apps Documents folder - ios

I have to download images to my iOS apps local file system and read them back.
On my simulator I can see file system of my app with directories
/Library/Developer/CoreSimulator/Devices/[UUID]/data/Containers/Data/Application/[UUID]/
/Documents
/Library
/tmp
To try out I copied foo.png to /Documents folder and then tried
<Image source={{uri: "file://Documents/foo.png"}} style={{width:100, height:100}}/>
This does not work, any idea whats a way to do this.

This also took me ages... with better info it would have been 5 minutes!
I use react-native-fs to get directories (which works for ios and android):
var RNFS = require('react-native-fs');
RNFS.DocumentDirectoryPath then returns something like '/var/mobile/Containers/Data/Application/15AC1CC6-8CFF-48F0-AFFD-949368383ACB/Documents' on iOS
My Image element looks like:
<Image
style={{width:100, height:100}}
source={{uri: 'file://' + RNFS.DocumentDirectoryPath + '/myAwesomeSubDir/my.png', scale:1}}
/>
My problem was that I did not set width and height first, which is not needed for urls or paths to assets. When using a base64 uri the width and height are also mandatory (that actually led me to the solution!).

Try tilda (~). React Native should expand that.
<Image
style={{width:100, height:100}}
source={{uri: '~/Documents/myAwesomeSubDir/my.png', scale:1}}
/>

Related

cordova-plugin-file: files not accessible after app update (iOS)

I am experiencing a funny problem: I am developing an ionic app, using cordova-plugin-file to store images. The resulting paths (URIs in form file:///...) are stored in a SQLite DB along with more information. When I install the app and use it, all works perfect. But if I update (or reinstall) the app, the old images are not found anymore, while newly added images work perfect.
I first suspected that the image files were being deleted on update, but I checked the content of the directory and the files are still there. (FYI: I am using file.dataDirectory/scans/ to place my files).
Then I thought that maybe I could go around the problem loading into img src a base64 blob loaded with cordova.file.readAsUrl(), but cordova.file does not find the file as well (I insist, the files are there, I checked with XCode).
So I checked further with cordova.file and it only finds files that are added after last app install, but the older files are still present in the directory.
Here my code:
private getImgSrcFromDocument(doc: Document): any {
const uri = doc.fileName;
const src = this.webView.convertFileSrc(uri);
const sanitized = this.sanitizer.bypassSecurityTrustUrl(src);
console.log({uri, src, sanitized});
return sanitized;
}
<img class="document_thumbnail" [src]="getImgSrcFromDocument(doc)">
I have already checked this, but is not my case.
By the way, the same code works perfect on Android.
Any idea what could be the problem?
Thanks in advance!
I found the reason why and the solution (very obvious when you know the problem):
Reason
On every new install, iOS renames the data directory for the app. The directory path has this form:
file:///var/mobile/Containers/Data/Application/ABC0000-1234-99DD-00FA-E835FEA/Library/NoCloud/
The hash in the middle is renewed on every install, so the stored full paths in DB are not valid anymore.
Solution
If you still can do it (no deploy yet, no real users), store only the relative path and complete it every time with this.file.dataDirectory (or wherever you wanted to store your files).
If you already have real users and want your update to 'find the files', just ignore the first part of the stored path and build it like before:
const ValidUri = this.file.dataDirectory + // The injected cordova-plugin-file
'relativeSubDirectories/' + // If you store your files in some subdirectory
this.document.storedFullPath.substr( // Take from fullPath only the filename
this.document.storedFullPath.lastIndexOf('/') + 1
);
Where storedFullPath is the string file:///var/mobile/....
After that, you still have to do the webView conversion and the sanitizing, like in the question above.
Hope this helps someone.

React Native thinks image is a module

This may seem like a duplicate but I've followed the answers to maybe a dozen similar questions on Stack and none of the solutions are working for me.
The React Native docs say load to local images like so:
<Image source={require('./my-icon.png')} />
I've placed the image 3D-home2#x.jpg in the same folder as the JS file:
I also tried placing it at the project root:
I also tried placing it in Images.xcassets and loading it like require('image!3D-home').
In between these efforts, I cleared the module cache several times with yarn start -- --reset-cache. Did a full XCode project 'clean' several times and rebuilt the app. No matter what I do I get some variation of this error (project name redacted):
What am I doing wrong here? It seems like I'm following the instructions exactly but I cannot get an image to load.
<Image
style={{
position: 'absolute',
width: '100%',
height: '100%',
top: 0,
left: 0,
zIndex: 10
}}
source={ require('./3D-home#2x.jpg') }
/>
The solution was to remove #2x from the file name. This is because React Native offers the ability to automatically swap out images using suffixes, so I was unwittingly trying to do that incorrectly or something:
You can also use the #2x and #3x suffixes to provide images for
different screen densities.
https://facebook.github.io/react-native/docs/images.html

React native: images with space in name won't load in IOS (device, not https issue)

Images with spaces in their name won't load in IOS, for android it worked by replacing the spaces with %20, but this solution didn't work on ios. React native.
I m loading the images remotely using uri, in a normal Image container. images without space load fine.
<Image source={{uri: fileName.replace(/ /g, '%20')}} style={styles.image} />
works on react-native#0.59.5
encodeURI("http://www.yourdomain.tld/sample image.jpg")
Output
http://www.yourdomain.tld/sample image.jpg
to
http://www.yourdomain.tld/sample%20image.jpg
Usage
<Image source={{uri: encodeURI(fileUri)}} />
the best way is to use the js builtin javascript function encodeURI
because we also have to convert some special characters in URLs

How can I display local images if I don't know their location before runtime?

var imageSource = require('./images/test.png')
<Image source={imageSource} style={s.userPic} />
That works great, but I need to show local photos just taken with the device (iPad) camera, so I won't know the local file location, stored in "user.imageLoc"...
var imageSource = eval("require('" + user.imageLoc + "')")
<Image source={imageSource} style={s.userPic} />
But that doesn't work. "Unknown module named (insert file location here)"
How can I display local images if I don't know their file name/address before runtime?
Pass image source as prop to your component :)
<MyCustomImageComponent imageSource={require(user.imageLoc)} />
If you want to access photos from your gallery or taken with the camera, maybe the best approach is to use the CameraRoll API from RN. v
This is the documentation:
https://facebook.github.io/react-native/docs/cameraroll.html
If that doesn't work or it's not what you want, we can try to find other solutions.

Image from custom.xcassets in React-Native

If we want to use an image in React-Native js from Images.xcassets, we simply provide the image name as URI - for eg.
<Image style = {styles.someStyle} source = {{uri:'addImage.png'}}>
But what if we have a custom created .xcassets ? How can that imageset be accessed from the RN js ?
It's considered as legacy code, but can be imported like:
<Image source={require('image!custom')} />

Resources