Images from Device storage custom path In React Native - react-native

I have an Image that I've downloaded and saved to the path /data/user/0/com.project/files/assets/image.png and I want to use this in my Image component in React-Native. Is there a way to use images stored in this path?
Ways to solve it that I have knowledge of but cannot use :
using require. which basically accepts literal strings that is not what I want for non-static images. names may change as per image for a single image source
using Native bundles, which is again I cannot use as the images are first being downloaded and then is being used.
using http links directly.which as again I cannot use as my feature states that the App cannot rely on network as it needs to render images in offline mode as well

If it's a file on your device, I think the way of displaying it is somewhat like this:
<Image source={{uri:'file:///data/user/0/com.project/files/assets/image.png'}} style={{width: 100, height: 100}}/>
Just make sure the file path is from the root. Hope it works for you.

Related

How to display image on local file system with Image?

The display for image from local file system stops work with Image in React Native 0.66. Here is the code:
<Image
source={{uri: img_source}}
.../>
Here img_source is a string returned by image picker (not from react-native-cameraroll). here is an example of imp_source in iOS emulator:
/Users/macair/Library/Developer/CoreSimulator/Devices/107E832C-4828-47D9-83D1-DABE20BA32F3/data/Containers/Data/Application/5C0BB55D-4834-47A9-B7CF-22CE9355C3FD/tmp/react-native-image-crop-picker/A52D733E-DB54-4C72-90DE-2444C3C45FD4.jpg
The app has the permission to pick up image from local gallery. Tried 'file://' + imp_source with no avail. How to make the code above working with Image?
Use the uri value from image picker. It looks like you're attaching a bunch of things prior to the root of the application in your URL. Without seeing the code, I'm assuming the URI should be file:///tmp/react-native-image-crop-picker/A52D733E-DB54-4C72-90DE-2444C3C45FD4.jpg, not the full system path.

Prevent React Native from caching local images

I have an app that makes heavy use of the Image component from React Native.
I understand that caching is good for remote images but I need to load local images which change regularly.
The Image component is caching the files and showing the cached version even when the local files change.
The question is how do I disable caching on local files but keep it for remote URLs (as I have a mix of local and remote)?
I would give a code example but literally it's as simple as
<Image source={{uri: 'file://image.png'}} />
Note: These are files that are created and changed by actions in the app so require('image.png') will not cut it. I use that for static images all the time and works great but it's static not dynamic.
I've also seen answers about random query params on the end of the string. That's very hacky in general so I wouldn't hire you for a job :) but apart from that it apparently doesn't work.
Cheers in advance!
To be really clear based on commments and answers to far....when the image file changes. It needs to change the image component immediately so caching and state need to be cleared and the new image is displayed.
A bit late to answer but you can add the query "?time=new Date()" in your variable, like that :
const [profilePicture] = useState(`${baseURL}${user.infoUser.image_profile}?time=${new Date()}`);
The main problem with this one is that is gonna refresh the image every time and oso the delay to display the image may be quite high.
Catching would be good for your app,so you don't want to stop. The solution to that sort of problem is to change the name of the image as well as the image itself. Changing the image without changing the name will do nothing.
You could have something like this
<Image source={{uri: `file://${imageName}`}} />,
that's the only piece of code you have posted so I can't really suggest more than that.
Better still you could store the imageName as part of state to be be able to re-render to a different anytime you feel like.
<Image source={{uri: `file://${this.state.imageName}`}} />
I think the problem is that there's no listener for changes on the image resource itself (and I don't think there's an library for that either). The only possible solution if you don't want to change the name of your file, would be to trigger an Event (or a state/redux - change) to force the component to reload everytime you change the Image in your code.
Otherwise you have to write your own library which always listens on image changes and reloads the component evertime something changes.

React native Image prefetch

I am having difficulties to understand Image prefetch. In the doc's there is not much explanation about it:
"Prefetches a remote image for later use by downloading it to the disk
cache"
Could you please help me understand the following about Image prefetch:
Suppose a user uploads a profile image, and the image's URL is stored in the AsyncStorage.
Should I run Image.prefetch(UserStore.profileImageUrl) only once after successful upload. And use prefetched image in the components normally like <Imagesource={{uri: UserStore.profileImageUrl}}/>
Or should I always run Image.prefetch(UserStore.profileImageUrl) before using that image in the component, then only run <Imagesource={{uri: UserStore.profileImageUrl}}/>
Suppose, later on, the user changes their profile image by uploading a new image and after successful upload, I will prefetch the new image. Will the previously cached image still exist on the disk?
If yes, won't it occupy a lot of space in the device if there are lots of prefetched images?
Is there any way to manually remove the prefetched image from the disk?
With the above questions in mind, if there are alternate solutions to achieve caching of images when using react native with expo, could you please help me with it.
It was indeed a question that I was dealing with for a while, and I learned a few things about Image.prefetch:
In the current React-Native version (0.48), this method is still in progress. To be more precise:
the ios implementation is still incomplete.
There is no complete guide on it.
There is no way to clear cache (you can check if the url is cached, however as far as I know you cannot clear it now).
As a result, I don't suggest you use it. Regardless, if you want to know how the API works, it is how:
Purpose
The purpose is quite obvious I think, this API:
Prefetches a remote image for later use by downloading it to the disk cache
It means that you can use Image.prefetch(url) in your constructor or componentWillMount. It tries to fetch image asynchronically, then, render your page with some kind of an ActivityIndicator, Finally, when the image is successfully fetched you can re-render your component.
Image.prefetch(url) actually saves the image to disk (not memory), as a result, whenever or wherever you try to use
<Image source={{uri:url}}/>
At firsts it checks the list of caches urls, if you have prefetched that url before (and it is located on the disk), it won't bother to re-fetch (unless you run function `Image.prefetch(url)' again (I am not sure if it works properly).
The implications of this issue are so complicated. It means that if you prefetch an image inside one component (for example <Component1/>), when you try to show this specific image in another component (for example <Component12>), It won't fetch the image and just uses the disk cache.
Therefore, either don't use this Image.prefetch at all (until there is a complete API, with cache control) or use it at your own risk.
on Android
On Android, you have 3 APIs for prefetch, and only one of them is presented in the documentation:
prefetch:
var response = Image.prefetch(imageUrl,callbackFunction)
Image.prefetch can have an optional second argument callbackFunction, which a function that runs Before fetching image. It can be written in the following format:
var response = Image.prefetch(imageUrl,()=>console.log('Image is being fetched'))
It might be worthy to note that, callbackFunction can have an argument called requestId, (indicating the number of prefetch among all other prefetches) which can be then used to abort the fetch.
var response = Image.prefetch(imageUrl,(id)=>console.log(id))
Moreover, response is a promise, you can use .then to do more after the image is pre-fetched.
abortPrefetch
Image.abortPrefetch(requestId) ;
used to abort the pending prefetch. requestId used as argument is the same as the one seen in prefetch.
queryCache
Image.queryCache([url1,url2, ...])
.then((data)=>console.log(data));
Used to check if a certain url is already cached, and if so where is it cached (disk or memory)
on IOS
I think that only Image.prefetch(url) is currently available on IOS, and there is no callback function to be called as the second argument.
if there are alternate solutions to achieve caching of images when
using react native with expo, could you please help me with it.
You may be interested in my higher order component module that adds performance related image caching and "permanent cache" functionality to the native <Image> component.
React Native Image Cache HOC
Tl;DR Code Example:
import imageCacheHoc from 'react-native-image-cache-hoc';
const CacheableImage = imageCacheHoc(Image);
export default class App extends Component<{}> {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<CacheableImage style={styles.image} source={{uri: 'https://i.redd.it/rc29s4bz61uz.png'}} />
<CacheableImage style={styles.image} source={{uri: 'https://i.redd.it/hhhim0kc5swz.jpg'}} permanent={true} />
</View>
);
}
}
The first image will be cached until the total local cache grows past 15 MB (by default) then cached images are deleted oldest first until total cache is below 15 MB again.
The second image will be stored to local disk permanently. People use this as a drop in replacement for shipping static image files with your app.
Personally I would not overcomplicate things by writing over files over and over when the file changes, that's just asking for a massive headache. Instead I would create a unique filename for each upload. So the user's profile pic the first time they upload is "profile-uniqueIdHere.jpg" and when they change their profile pic you just create a new file "profile-anotherUniqueIdHere.jpg" and update their user data to reflect the new file location. For help with creating unique Ids look at react-native-uuid.

Setting ApplicationBarButton.IconUri with icon from Isolated Storage

I am working on windows phone application in which i need to change ApplicationBarButton icon dinamically, for example to show current date like in default Windows Phone Calendar app. Regarding to this article, we can use only png images previously added to solution and reference to them with relative Uri.
It is not a problem for me to generate correct png image (this way and using ToolStack C# PNG Writer Library) and save it to isolated storage, but when i'm initializing AppBarButton with absolute Uri to this image and trying to add it to ApplicationBar, my app throws ArgumentException.
Am i doing something wrong or i just have to draw 366 icons and add them to my project? :)
Thanks in advance!

Fine Uploader: resizing large files before upload?

I'm evaluating Fine Uploader compared to various other options, specifically JQuery File Upload.
I generally prefer the Fine Uploader approach as it's more lightweight, compared to JQuery File Uploader which has dependencies on Bootstrap and JQuery UI.
However it's important to be able to resize images: e.g., a user may select a large file from their camera and this may be very large - uploading the full resolution photo may take a very long time. JQuery File Upload doe this.
Additionally we don't have much use for very high resolution files.
If possible (I'm aware some browsers may not support this), I'd like to be able to resize images client size.
Is this possible?
Fine Uploader does not currently have any native support for image manipulation. This is a feature in our backlog, but we have not had many users tell us they are interested in this. This is one of the reasons why such a feature has yet to be implemented natively. There is a case, #707 that marks the start of native image-editing support for Fine Uploader. It is tentatively scheduled for 4.0.
However, you can certainly make use of FileReader and Canvas to resize the image. You can then submit this resized image as a Blob to Fine Uploader via the addFiles API method. At that point, the file has been submitted and Fine Uploader is ready to upload the item.
Essentially, the steps you would follow to handle this specific scenario, before Fine Uploader natively supports image manipulation:
Provide your own file input element(s) or make use of Fine Uploader's file/folder drag and drop support to get a handle on some files selected by the user.
Use FileReader to read the contents of the image.
FileReader will provide you with a URL for the image, assign that to the src attribute of an img element.
Draw the img onto a canvas element. This is where the resizing occurs.
Grab the URL of the resized image from the canvas element (canvas.toDataURL(...)).
Convert the URL to a Blob.
Pass the Blob to the addFiles API method of Fine Uploader.
The intent is to take care of most if not all of this for integrators such as yourself in the future by adding native image manipulation support to Fine Uploader.
Hope this helps.