React-Native: Convert image url to base64 string - javascript

I'm building a react native app that needs to store images at base64 string format for offline viewing capabilities.
What library / function would give me the best result to store the image as base64 string? assuming my url is "http://www.example.com/image.png".
Also, do I need to make http request to get it before storing it as a string? my logic says yes, but in react native you can load images on the <Image> component without request them first from the server.
What would be the best option to do this in react native?

I use rn-fetch-blob, basically it provides lot of file system and network functions make transferring data pretty easy.
react-native-fetch-blob is deprecated
import RNFetchBlob from "rn-fetch-blob";
const fs = RNFetchBlob.fs;
let imagePath = null;
RNFetchBlob.config({
fileCache: true
})
.fetch("GET", "http://www.example.com/image.png")
// the image is now dowloaded to device's storage
.then(resp => {
// the image path you can use it directly with Image component
imagePath = resp.path();
return resp.readFile("base64");
})
.then(base64Data => {
// here's base64 encoded image
console.log(base64Data);
// remove the file from storage
return fs.unlink(imagePath);
});
source Project Wiki

There is a better way:
Install this react-native-fs, IF you don't already have it.
import RNFS from 'react-native-fs';
RNFS.readFile(this.state.imagePath, 'base64')
.then(res =>{
console.log(res);
});

ImageEditor.cropImage(imageUrl, imageSize, (imageURI) => {
ImageStore.getBase64ForTag(imageURI, (base64Data) => {
// base64Data contains the base64string of the image
}, (reason) => console.error(reason));
}, (reason) => console.error(reason));

The standalone expo FileSystem package makes this simple:
const base64 = await FileSystem.readAsStringAsync(photo.uri, { encoding: 'base64' });
https://docs.expo.io/versions/latest/sdk/filesystem/
https://github.com/expo/expo/tree/master/packages/expo-file-system
As 2019-09-27 this package handles both file:// and content:// uri's

To convert image to base64 in React native, the FileReader utility is helpful:
const fileReader = new FileReader();
fileReader.onload = fileLoadedEvent => {
const base64Image = fileLoadedEvent.target.result;
};
fileReader.readAsDataURL(imagepath);
This requires react-native-file.
Another alternative, and probably the preferred alternative, is to use NativeModules. The Medium article shows how. It requires creating a native module.
NativeModules.ReadImageData.readImage(path, (base64Image) => {
// Do something here.
});

You can use react-native-image-base64. You have to give image url and it returns the base64 string of image.
ImgToBase64.getBase64String('file://youfileurl')
.then(base64String => doSomethingWith(base64String))
.catch(err => doSomethingWith(err));

In case you're using expo in a managed workflow and cannot use react-native-fs, you can do it using the expo-file-system library. Here's a helper function that will do the trick by only providing an image URL and will return a base64 encoded image.
PS: It doesn't contain the base64 prefix, you need to include it yourself based on the image type you have.
import * as FileSystem from 'expo-file-system';
async function getImageToBase64(imageURL) {
let image;
try {
const { uri } = await FileSystem.downloadAsync(
imageURL,
FileSystem.documentDirectory + 'bufferimg.png'
);
image = await FileSystem.readAsStringAsync(uri, {
encoding: 'base64',
});
} catch (err) {
console.log(err);
}
return image;
}
An example usage in a React Native Image component is as follows:
<Image
style={{ width: 48, height: 48 }}
source={{ uri: `data:image/png;base64,${image}` }}
/>

react-native-image-picker includes a base64 data node in the returned object. fyi

If You are using **react-native-image-picker**
Then it includes base64 string in response object
if you are using any other library i.e. **react-native-document-picker**
then you have to use **react-native-fs** library
import RNFS from 'react-native-fs';
RNFS.readFile(item.uri, 'base64').then((res) => {
//Here in enter code here res you will get base64 string
});

No library need, use built in JS features
export default async function base64File(url) {
const data = await fetch(url);
const blob = await data.blob();
return new Promise(resolve => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64data = reader.result;
resolve(base64data);
};
});
}

i am using react-native-image-crop-picker
add includeBase64 prop it will response in base64 converted image
ImagePicker.openPicker({
width: 300,
height: 400,
includeBase64:true
}).then(image => {
console.log(image.data);
});

I used another package: react-native-fs
import RNFS from 'react-native-fs';
var data = await RNFS.readFile( "file://path-to-file", 'base64').then(res => { return res });
This works fine.

For me upalod file mp4 from local file on devies to Facebook or another social:
var data = await RNFS.readFile( `file://${this.data.path}`, 'base64').then(res => { return res });
const shareOptions = {
title: 'iVideo',
message: 'Share video',
url:'data:video/mp4;base64,'+ data,
social: Share.Social.FACEBOOK,
filename: this.data.name , // only for base64 file in Android
};
Share.open(shareOptions).then(res=>{
Alert.alert('Share Success`enter code here`!')
}).catch(err=>{
console.log('err share', err);
});

import ImgToBase64 from 'react-native-image-base64';
ImgToBase64.getBase64String(trainingRooms)
.then(base64String => {
console.log("Sourabh____ ImgToBase64 base64String "+base64String );
})
.catch(err => {
console.log("Sourabh____ ImgToBase64 error "+err);
})

Convert url image to base64
const getBase64ImageFromUrl = url =>
fetch(url)
.then(response => response.blob())
.then(
blob =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
blob = new Blob([blob], {type: 'image/png'});
reader.readAsDataURL(blob);
}),
);
await getBase64ImageFromUrl("https://your image url");

Related

Downloading an mp3 file from S3 and manipulating it results in bad file

I did a script that downloads a MP3 file from my S3 bucket and then manipulates in before download (Adding ID3 Tags).
It's working and the tags are injected properly, but the files corrupts as it seems and unplayable.
I still can see my tags trough MP3tag so it has data in it, but no audio is playing trough the file.
Heres my code,
Trying to figure it what went wrong
const downloadFileWithID3 = async (filename, downloadName, injectedEmail) => {
try {
const data = await s3Client.send(
new GetObjectCommand({
Bucket: "BUCKETNAME",
Key: filename,
})
);
const fileStream = streamSaver.createWriteStream(downloadName);
const writer = fileStream.getWriter();
const reader = data.Body.getReader();
const pump = () =>
reader.read().then(({ value, done }) => {
if (done) writer.close();
else {
const arrayBuffer = value;
const writerID3 = new browserId3Writer(arrayBuffer);
const titleAndArtist = downloadName.split("-");
const [artist, title] = titleAndArtist;
writerID3.setFrame("TIT2", title.slice(0, -4));
writerID3.setFrame("TPE1", [artist]);
writerID3.setFrame("TCOM", [injectedEmail]);
writerID3.addTag();
let taggedFile = new Uint8Array(writerID3.arrayBuffer);
writer.write(taggedFile).then(pump);
}
});
await pump()
.then(() => console.log("Closed the stream, Done writing"))
.catch((err) => console.log(err));
} catch (err) {
console.log(err);
}
};
Hope you can help me solve this wierd bug,
Thanks in advance!
Ok so i've figured it out, instead of using chunks of the stream itself i've used getSignedUrl from the s3 bucket it works.
Thanks everyone for trying to help out!

Convert axios response to Blob url image to display/download it in website

I'm using the Egnyte API
I don't understand how the response object works, I tried to convert the data to Blob object and URL.createObjectURL but this doesn't work for me. I don't know if I can display this images to my website.
DOCS Egnyte API: LIST FILE OR FOLDER
This problem also happens to me when I want to download the image, because the api response returns plain encrypted text and I don't know how I can convert it into an object to download it with javascript/html
DOCS Egnyte API: DOWNLOAD FILE
Axios get images from Egnyte API
const getImages = () => {
axios.get(`${API}/${params.id}/images/`, config).then(res => {
setImagesList(res.data.files)
}).catch((error) => {
console.log(error)
})
}
The response looks like this:
Convert item to Blob object and URL.createObjectURL
const displayImg = (list_images) => {
return list_images.map(img => {
const url = URL.createObjectURL(new Blob([img]))
return (
<div className='div_img' key={img.name}>
<img src={url} />
</div>
)
})
}
The URL object looks like this:
But the website looks:
Response from API DOWNLOAD FILE:
I would be very grateful if someone could explain to me how I can convert the API response into an image object to be able to show it and download it (and files to download).
Thank you very much!
Use the FileReader to turn the blob into a base64 string that can be used as an image source (something like data:image/png;base64,...) - this post shows you how:
function blobToBase64(blob) {
return new Promise((resolve, _) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
https://stackoverflow.com/a/18650249/1143126
This function can be used to process the result that axios gives you, somewhat like this:
axios.get(...)
.then(blobToBase64)
.then(base64 => {
// I'm assuming there is a variable 'imageSource' that is bound to the 'src' attribute of an HTML '<img>' somewhere
imageSource = base64;
})
.catch((error) => {
// do error handling
});

Encode and decode javascript file or blob to base64

I am creating a web app with react as frontend and python ariadne (graphql) as backend. I want to allow the user to upload a file.
Essentially, I first want to convert the file to base64 in react, pass it to graphql mutation, and then decode the base64 string back to file in javascript.
Just like base64.b64encode & base64.b64decode in python.
Is there a way to this with a javascript file or blob object?
You can convert a file but note that it's an async call:
const toBase64 = file => new Promise((resolve, reject) => {
const r = new FileReader();
r.readAsDataURL(file);
r.onerror = error => reject(error);
r.onload = () => resolve(reader.result);
});
// use with await toBase64(YOUR_FILE);
To reconvert the base64 to a file use this:
fetch(YOUR_DATA)
.then(res => res.blob())
.then(blob => {
const file = new File([blob], "YOUR_FILE_NAME" ,{ type: YOUR_MIME_TYPE })
})

How can I set the downloaded filename when using Filereader API?

I have a document as a base64string and then I generate the File from this and provide a download link. This all works correctly, however it gives the file a random number rather than the name I want.
Firstly I create a new file like so:
export const urlToFile = (url, filename, type) =>
fetch(url)
.then(res => res.arrayBuffer())
.then(
buffer =>
new File([buffer], filename, {
type
})
);
export const getExportFileUrl = resp =>
urlToFile(
`data:${docType};base64,${resp}`,
`Document_Filename`,
`${docType}`
).then(file => file);
I then combine Filereader and URL Api's to create the download link like so:
// This is returned from the File API.
const exportedFile = {
name: "Document_Filename"
lastModified: 1587577801489
lastModifiedDate: '....'
webkitRelativePath: ""
size: 8243
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}
handleDownloadClick = () => {
const fileReader = new FileReader();
fileReader.onload = () => {
const downloadUrl = URL.createObjectURL(exportedFile);
window.location = downloadUrl;
};
fileReader.readAsText(exportedFile);
};
The filename downloaded is something like:
f8477d6a-bea9-4a83-843f-26e381249b71.docx
How can I set my own filename, is this possible with the above implementation?
The solution was to utilize an anchor element rather than a button and then set the download attribute with the name I wanted for the file like so:
<a download="Name_2020_04_23_12_39" href="blob:http://domain">Download</a>

Save Blob to FileSystem in React Native Expo

I am trying to download a PDF and share it via the 'expo-sharing' SDK. I can't use FileSystem.createDownloadResumable because the document is available via a POST request.
Download it as a blob and use FileReader to convert it to a base64 string to pass to FileSystem.writeAsStringAsync
const response = await axios.post(URL_PDF_CONTENT, { Benefits: payload }, { responseType: 'blob' });
const fr = new FileReader();
fr.onload = async () => {
const fileUri = `${FileSystem.documentDirectory}/pdf.pdf`;
await FileSystem.writeAsStringAsync(fileUri, fr.result.split(',')[1], { encoding: FileSystem.EncodingType.Base64 });
Sharing.shareAsync(fileUri);
};
fr.readAsDataURL(response.data);

Categories

Resources