base64 image not sharing in react native android - react-native

I am using react-native-share to share something in hangouts, whatsapp and so on... here is my code that i tried,
i imported the
import RNFetchBlob from 'react-native-fetch-blob';
import Share from 'react-native-share';
so used RNFetchblob to convert image url to base64, and added the dependencies based on the api.
_downloadImageAndShare(title, message, url) {
const { fs } = RNFetchBlob.fs;
var self = this;
RNFetchBlob.config({ fileCache: true })
.fetch('GET', url)
.then(resp => {
return resp.readFile('base64')
.then(base64 => {
return { resp, base64 };
})
})
.then(obj => {
console.log(obj)
var headers = obj.resp.respInfo.headers;
var type = headers['Content-Type'];
var dataUrl = 'data:' + type + ';base64,' + obj.base64;
console.log('dataurl is', dataUrl)
return { title, message, url: dataUrl };
})
.then(options => {
return Share.open(options);
console.log('options is', options)
}).catch(err => {err && console.log(err); })
}
<ShareIcon onTrigger={ () => this._downloadImageAndShare('sample', `${title} sample. More http://www.sample.com`, shareImage) } white={!!whiteIcon} />
here I am getting the response image url converted in base64 format. I want to share the a content , link and the image. These procedure working fine in iOS.
But in android image is not getting share.

Related

Convert Base64 to png and save in the device React Native Expo

I've been trying to save an image on a mobile device with React Native and Expo, i have tried with these packages:
import RNFetchBlob from 'react-native-fetch-blob';
import RNfs from 'react-native-fs ';
but both give me this error when implementing them
null is not an object (evaluating 'RNFetchBlob.DocumentDir')
then try expo-file-system but i don't see any clear example of how to convert base64 and download it to mobile
UPDATE
I was able to do it, my purpose was to save the base64 of a QR and convert it to png and at the same time be able to share it, I did it using expo-file-system and expo-sharing
this is mi code,
import * as FileSystem from 'expo-file-system';
import * as Sharing from 'expo-sharing';
//any image, I use it to initialize it
const image_source = 'https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80';
share=()=>{
var self = this;
self.setState({loading:true})
FileSystem.downloadAsync(
image_source,
FileSystem.documentDirectory + '.png'
)
.then(({ uri }) => {
console.log(self.state.base64Code);
FileSystem.writeAsStringAsync(
uri,
self.state.base64Code,
{'encoding':FileSystem.EncodingType.Base64}
)
.then(( ) => {
this.setState({loading:false})
Sharing.shareAsync(uri);
})
})
.catch(error => {
console.error(error);
});
}
Actually, I don't know if it's the best way, first write a png image in the directory and then rewrite it with the base64 code, but it worked
This worked for me:
const data = "data:image/png;base64,ASDFASDFASDf........"
const base64Code = data.split("data:image/png;base64,")[1];
const filename = FileSystem.documentDirectory + "some_unique_file_name.png";
await FileSystem.writeAsStringAsync(filename, base64Code, {
encoding: FileSystem.EncodingType.Base64,
});
const mediaResult = await MediaLibrary.saveToLibraryAsync(filename);
Thanks for the update. I've been struggling for days with this on Android and base64 images!
In my case i was trying to upload a base64 image from a signature pad on expo and always got "Network request failed"
I managed to make it work like this hope it helps!
import * as FileSystem from 'expo-file-system';
const uploadBase64 = async (base64String) => {
this.setState({ uploading: true });
//Without this the FilySystem crashes with 'bad base-64'
const base64Data = base64String.replace("data:image/png;base64,","");
try {
//This creates a temp uri file so there's no neeed to download an image_source to get a URI Path
const uri = FileSystem.cacheDirectory + 'signature-image-temp.png'
await FileSystem.writeAsStringAsync(
uri,
base64Data,
{
'encoding': FileSystem.EncodingType.Base64
}
)
//At this point the URI 'file://...' has our base64 image data and now i can upload it with no "Network request failed" or share the URI as you wish
const uploadResult = await this.uploadImageAsync(uri).then(res => res.json())
if (uploadResult) {
this.setState({ image: uploadResult.location });
}
this.setState({ uploading: false });
} catch (e) {
this.setState({ uploading: false });
console.log('*Error*')
console.log(e)
}
}
//Just and ordinary upload fetch function
const uploadImageAsync = (uri) => {
let apiUrl = 'https://file-upload-example-backend-dkhqoilqqn.now.sh/upload';
let formData = new FormData();
formData.append('photo', {
uri,
name: `photo.png`,
type: `image/png`,
});
let options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
return fetch(apiUrl, options);
}

nativescript image upload to s3 encoding issue

I'm having issues uploading an image from Nativescript to AWS, and I'm pretty sure it's a configuration issue.
select an image
const context = imagepicker.create({
mode: 'single' // use "multiple" for multiple selection
});
await context.authorize();
const selection: Array<ImageAsset> = await context.present();
const imageAsset = selection[0];
const source: ImageSource = await new ImageSource().fromAsset(imageAsset);
const fileLocation = imageAsset.android ? imageAsset.android : imageAsset.ios;
const fileType = mime.extension(mime.lookup(fileLocation));
const image = source.toBase64String(fileType);
console.log(image);
image at this point is: iVBORw0KGgoAAAANSUhEUgAAB4AAAASwCAIAAACVUsChAAAAA3NCSVQI...
image location at this point is: /storage/emulated/0/DCIM/Screenshots/Screenshot_20181106-150854.png
const fileLocation = imageAsset.android ? imageAsset.android : imageAsset.ios;
const signedUrl = await this.getSignedUrl(fileLocation);
Backend Code to get signedURL
const getSignedUrlPromise = (operation, params) => {
return new Promise((resolve, reject) => {
s3.getSignedUrl(operation, params, (err, url) => {
err ? reject(err) : resolve(url);
});
});
}
const params = {
Bucket: BUCKET_NAME,
Key: `abc123/456/3/${fileName}`,
ContentType: contentType,
ContentEncoding: 'base64'
}
const url = await getSignedUrlPromise('putObject', params).catch(err => {
console.log('error', JSON.stringify(err))
return {
statusCode: 400,
body: JSON.stringify(err)
}
});
console.log('success', url);
return {
statusCode: 200,
body: JSON.stringify({ url: url })
}
signedUrl at this point is:
https://myproject.s3.amazonaws.com/abc123/456/3/Screenshot_20181106-150854.png?AWSAccessKeyId=xxxxxxxxxxxxxx&Content-Encoding=base64&Content-Type=image%2Fpng&Expires=1555517358&Signature=yyyyyyyy&x-amz-security-token=long_token
Then, using the signedURL, i upload the image:
const mimeType = mime.lookup(fileLocation);
this.http.put(signedUrl, image, {
headers: {
'Content-Type': mimeType,
'Content-Encoding': 'base64'
}
}).subscribe((resp) => {
console.log('resp2', resp);
});
}
When I open the file, this is what I see
and the meta-data on the S3 object looks correct
When I download the file and open it in NP++, I see the base64 value.
iVBORw0KGgoAAAANSUhEUgAAB4AAAASwCAIAAACVUsChAAAAA3NCSVQI...
I also cannot open the downloaded image
ATTEMPT 2
I saw where some people were using buffers, so I changed my image code to
const image = Buffer.from(source.toBase64String(fileType).replace(/^data:image\/\w+;base64,/, ''), 'base64');
which the image is still broken, and when I download and open the file using NP++ I see
{"type":"Buffer","data":[137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,7,128,0,0,4,176,8,2,0,0,0

Display profile picture with expo

I am new to React native and expo and I'm trying to handle the user's profile (edit the profile, profile picture, etc...).
I managed to successfully retrieve the user's info from the API and send the changes like the username or password to it but I can't do it for the profile picture.
I've already tried with axios (what I use to communicate to the API):
async componentDidMount() {
const token = await this.getToken();
const AuthStr = 'Bearer '.concat(token);
await axios.get('https://....jpg', { headers: { Authorization: AuthStr } })
.then(res => {
console.log('RESPONSE: ', res.data);
})
.catch((error) => {
console.log('error ' + error);
});
}
But it returns me error 500
Then I tried with the FileSystem from Expo:
let download = FileSystem.createDownloadResumable('https://...jpg',
FileSystem.documentDirectory + 'profile.jpg',
{ headers: { Authorization: AuthStr } },
null,
null);
try {
const { uri } = await download.downloadAsync();
console.log('Finished downloading to ', uri);
this.setState({
pic: uri,
});
} catch (e) {
console.error(e);
}
let info = await FileSystem.getInfoAsync(this.state.pic, null);
console.log(info);
The log says the file is downloaded and the path is something like this:
file:///var/mobile/Containers/Data/Application/20CF6F63-E14D-4C14-9078-EEAF50A37DE1/Documents/ExponentExperienceData/%2540anonymous%app/profile.jpg
The getInfoAsync() returns true, meanings that the image exists in the filesystem. When I try to render it with
<Image source={{uri: this.state.pic}}/>
It displays nothing. What do I do wrong ?
the temporary solution is to move the image to the gallery
let { uri } = await FileSystem.downloadAsync(this.props.item.imgUrl, FileSystem.cacheDirectory + ${this.props.item}.jpg);
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status === 'granted') {
CameraRoll.saveToCameraRoll(uri).then((uriGallery) => {
//here you have the url of the gallery to be able to use it
});
}
This is the link I referred to in writing the answer.

React Native - send image from local cache to firebase storage

With React Native on Android I am trying to send the image profile of the user from local cache to a firebase storage bucket. If I send it as blob or Uint8Array, when I open the image on firebase I get the error The image "https://firebasestorage<resto of url here>" cannot be displayed because it contain errors. If I send it as base64 data url,it does not upload to the bucket and I get the message Firebase Storage: String does not match format 'base64': Invalid character found. I have tested the base64 data url with a decoder and it works. How can I get this to work, either as blob, Uint8Array or base64?. Here is the code:
As blob
let mime = 'image/jpeg';
getFile(imageUri)
.then(data => {
return new Blob([data], { type: mime });
})
.then(blob => {
return imageRef.put(blob, { contentType: mime });
})
async function getFile(imageUri) {
let bytes = await FileSystem.readAsStringAsync(imageUri);
return Promise.resolve(bytes);
}
As Uin8Array
let mime = 'image/jpeg';
getFile(imageUri)
.then(data => {
return imageRef.put(data, { contentType: mime });
})
async function getFile(imageUri) {
let bytes = await FileSystem.readAsStringAsync(imageUri);
const imageBytes = new Uint8Array(bytes.length);
for ( let i = 0; i < imageBytes.length; i++) {
imageBytes[i] = bytes.charCodeAt(i);
}
return Promise.resolve(imageBytes);
}
As base64 data url
imageBase64Url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAF0lEQVQI12P8//8/AwMDAwMDEwMMIFgAVCQDA25yGkkAAAAASUVORK5CYII=";
return imageRef.putString(imageBase64Url, 'data_url');
The URI
I retrieve the uri from this object:
Object {
"cancelled": false,
"height": 60,
"type": "image",
"uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FMCC_Project-ee81e7bd-82b1-4624-8c6f-8c882fb131c4/ImagePicker/6ec14b33-d2ec-4f80-8edc-2ee501bf6e92.jpg",
"width": 80,
}
We found at least two problems with the way I was trying to retrieve the picture and send it to the Firebase bucket:
1) When retrieving the image from memory and trying to send it as blob to the bucket, FileSystem.readAsStringAsync(imageUri) was returning for some reason a corrupted file
2) Instead when trying to save the image to Firebase bucket as base64, the problem seems to be with firebase, since not even the very same examples provided here https://firebase.google.com/docs/storage/web/upload-files were working.
The solution:
We retrieved the image from local cache with XMLHttpRequestinstead of Expo's FileSystem, and saved it to Firebase bucket as blob:
import React, { Component } from 'react';
import firebase from './firebase';
export default async function saveImage(picture, uid) {
const storageRef = firebase
.storage('gs://*<bucket-here>*')
.ref(uid + '/' + 'profile-picture.jpeg');
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', picture.uri, true);
xhr.send(null);
});
const metadata = {
contentType: 'image/jpeg',
};
return (downloadURL = await new Promise((resolve, reject) => {
try {
storageRef.put(blob, metadata).then(snapshot => {
snapshot.ref.getDownloadURL().then(downloadURL => {
resolve(downloadURL);
});
});
} catch (err) {
reject(err);
}
}));
}

Trying to extract text through OCR space API in react native but receiving an error as incorrect base64 format

After clicking an image through android mobile and extracting base64 from the image, I am sending it to the OCR space API to extract the text in the image.
getTextByURL is subjected to call the API after receiving the base64.
The format should be data:image/png;base64,iVBORw0KGgoAAAANS....
To obtain the format I am appending the base64 code to 'data:image/png;base64,' which should satisfy the required POST call conditions.
But the error still persists, I could not find whether the error is in the format or in the base64 code.
When I give a base64 code of an image in the POST call instead of base64 generated from the clicked image, the API call is working.
So no idea where is the glitch.
please help me!
getTextByUrl(base) {
var url = "https://api.ocr.space/parse/image";
var subscriptionKey = "xxxxxxxxxxxxxx";
var data = new FormData();
data.append("apikey", subscriptionKey);
data.append("language", "eng");
data.append("isOverlayRequired", "true");
data.append("Base64Image", base)
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
alert(this.responseText);
}
});
xhr.open("POST", "URL");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.send(data);
}
showCamera() {
this.setState({
showComponent: true,
uri: ""
})
}
The following function is to click the image and extract the base64 from the image.
takePicture() {
const options = {};
//options.location = ...
this.camera.capture({ metadata: options })
.then((data) => {
let pathToImage = data.path;
CompressImage.createCompressedImage(pathToImage, 'compress/images').then(
ImgToBase64.getBase64String(pathToImage)
.then(base64String => {
**base64String = "data:image/jpg;base64," + base64String;**//This gives the base64 of the image
alert(base64String.substring(0, 50) + typeof (base64String));
this.setState({
baa: base64String.substring(0, 200)
})
this.getTextByUrl(base64String)
})
.catch(err => alert(err))
)
})
.catch(err => console.error(err));
}
Thanks in advance.
May be replace "Base64Image" with "base64Image". This works for me
const data = await this.camera.takePictureAsync(options);
const base64Str = 'data:image/jpg;base64,'+data.base64; var data = new FormData();
data.append('apikey', key)
data.append('base64Image', base64)
const headers = {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data;',
}
const config = {
method: 'POST',
headers,
body: data
};
const URL = 'https://api.ocr.space/parse/image';
fetch(URL, config )