Save Blob to FileSystem in React Native Expo - javascript

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);

Related

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 })
})

Upload .vhd as Page-Blob to azure-blob-storage from Url

i have a bunch of VHD files stored on a private Server, which are accessible through a url.
I am trying upload these vhd files directly to my azure storage account using the azure javascript npm libraries. The vhds have to be uploaded as page-blobs. I tried using the method uploadPagesFromURL() of the pageblobClient but with no success. My code looks roughly like this:
async function uploadVHD(accessToken, srcUrl)
{
try {
// Get credentials from accessToken
const creds = new StorageSharedKeyCredential(storageAccount.name, storageAccount.key);
// Get blobServiceClient
const blobServiceClient = new BlobServiceClient(`https://${storageAccount.name}.blob.core.windows.net`, creds);
// Create Container
const containerClient = blobServiceClient.getContainerClient("vhd-images");
await containerClient.createIfNotExists();
const src = srcUrl.replace('https://', 'https://username:password#');
// Upload to blob storage
const pageBlobClient = containerClient.getPageBlobClient("Test.vhd");
// Get fileSize of vhd
const fileSize = (await axiosRequest(src, { method: "HEAD" })).headers["content-length"];
const uploadResponse = await pageBlobClient.uploadPagesFromURL(src, 0, 0, fileSize);
return uploadResponse;
} catch (error) {
return error;
}
});
It is not possible to upload the Page Blob with your URL directly. You need to read data from the url. Then upload using uploadPages method.
axios.get(URL, {
responseType: 'arraybuffer'
})
.then((response) => {
console.log(response.data)
console.log(response.data.length)
// upload page blob...
}).catch((error) => {
//handle error
});
// uploadPages method
const uploadResponse = pageBlobClient.uploadPages(data, 0, dataLength);

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>

How to post original file as formdata using api with filestack in reactjs?

I am using filestack in react to upload files. First i browse the images and upload it, on
Upload Done i am using a function, in this function i want to post original file as formdata
using my api with post method. So help me to post original file to my server after getting
response from filestack upload.
const options = {
maxFiles: 5,
onUploadDone: handleUploadFunction // callback function on upload done
};
const filestack = client.init("key", options);
const picker = filestack.picker(options);
function handleUploadFunction(result, board_id) {
const fileData = result.filesUploaded[0];
console.log(result);
const getValue = sessionStorage.getItem("user_id");
const token = sessionStorage.getItem("userToken");
let imageData = new FormData();
imageData.append("v_code", "1.0");
imageData.append("apikey", "41bbf547d64c309749b613f16323b762");
imageData.append("token", token);
imageData.append("userid", getValue);
imageData.append("board_id", 362);
imageData.append("img_text", "Test Image 362");
imageData.append("img_data", "image data 362");
imageData.append("card_id", 8854);
imageData.append("image", fileData.originalFile);
axios.post("http://160.153.247.88:3000/add_file", imageData).then(res => {
console.log(res.data);
});
}

React-Native: Convert image url to base64 string

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");

Categories

Resources