Reputation: 126
I am trying to learn react native and how to download files to the device. I know you can do this with react native file system but that does not support authentication which I need. React native fetch blob does support this.
For education purposes, I want to have the code from the first answer to this question recreated in react native fetch blob instead of react native file system.
I someone could write sutch an examlple form me I would be super tankfull.
Question: Downloading data files with React Native for offline use
Upvotes: 0
Views: 8085
Reputation: 1
Inject JS to handle the blob file download(injected JS should be wrapped inside ``).
const injectedJS = `(function() {
window.ReactNativeWebView.postMessage = function(data) {
window.ReactNativeWebView.postMessage(JSON.stringify(data));
};
document.addEventListener('click', function(e) {
const element = e.target;
const anchor = document.querySelector('a[href^="blob:"]');
if (anchor && anchor.getAttribute('href')) {
e.preventDefault();
const xhr = new XMLHttpRequest();
let href = anchor.getAttribute('href')
const fileName = anchor.getAttribute('download') || 'downloaded-file';
fetch(href)
.then(response => response.blob())
.then(blob => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
const base64Data = reader.result.split(',')[1];
window.ReactNativeWebView.postMessage(JSON.stringify({
base64Data: base64Data,
fileName: fileName
}));
};
})
.catch(error => {
console.error('Failed to fetch blob data:', error);
});
} else {
console.log('href not loaded yet.');
}
});
})()`;
const handleMessage = async event => {
try {
const { base64Data, fileName } = JSON.parse(event.nativeEvent.data);
if (!base64Data) {
throw new Error('Base64 data is undefined');
}
const filePath = `${RNBlobUtil.fs.dirs.DownloadDir}/${fileName}`;
// Save the Base64 data as a file
await RNBlobUtil.fs.writeFile(filePath, base64Data, 'base64');
// Trigger a download intent on Android
await RNBlobUtil.android.actionViewIntent(filePath, 'application/pdf');
} catch (error) {
console.error('File download error:', error);
}
};
<WebView
source={{
uri
}}
allowsBackForwardNavigationGestures
bounces
cacheEnabled={false}
contentMode="mobile"
domStorageEnabled={true}
geolocationEnabled
incognito
javaScriptCanOpenWindowsAutomatically
javaScriptEnabled={true}
mixedContentMode="compatibility"
originWhitelist={['https:*', 'blob:*']}
ref={webViewRef}
scalesPageToFit
sharedCookiesEnabled
startInLoadingState={true}
style={styles.container}
thirdPartyCookiesEnabled
onLoadEnd={() => {
webViewRef.current?.injectJavaScript(injectedJS);
}}
onMessage={handleMessage}
/>
Upvotes: 0
Reputation: 263
downloadImage(){
var date = new Date();
var url = "http://debasish.com/image.jpg";
var ext = this.getExtention(url);
ext = "."+ext[0];
const { config, fs } = RNFetchBlob ;
let PictureDir = fs.dirs.PictureDir
let options = {
fileCache: true,
addAndroidDownloads : {
useDownloadManager : true,
notification : true,
path: PictureDir + "/image_"+Math.floor(date.getTime()
+ date.getSeconds() / 2)+ext,
description : 'Image'
}
}
config(options).fetch('GET', url).then((res) => {
Alert.alert("Download Success !");
});
}
getExtention(filename){
return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) :
undefined;
}
Upvotes: 1
Reputation: 677
Try this, it's work fine on Android:
export const download = (url, name) => {
const { config, fs } = RNFetchBlob;
let PictureDir = fs.dirs.PictureDir;
let options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true,
notification: true,
path: PictureDir + name,
description: t('downloading_file')
}
};
config(options)
.fetch('GET', url)
.then(res => {
if (res.data) {
alert(t('download_success'));
} else {
alert(t('download_failed'));
}
});
};
Upvotes: 1