Use PDF utilities
Overview
In this section teaches you how to use the PDF utilities (download and preview) in a Etendo subapp.
Info
This tutorial requires an already functional subapp. If you don't have the environment, please follow the steps in [Getting Started]](/developer-guide/etendo-mobile/getting-started/){target="_blank"} in the Etendo Mobile section.
Setup
Checking dependencies
Before starting, make sure you have the following dependencies listed in package.json and installed:
- react-native-blob-util version 0.19.4
- react-native-pdf version 6.7.1
- react-native-share version 10.0.2
Hook creation
In the hook folder of your subapp, create a new file called usePDF.tsx and paste the following code:
import { useState } from 'react';
import { Platform } from 'react-native';
import ReactNativeBlobUtil from 'react-native-blob-util';
import Share from 'react-native-share';
// Simple verification to check if the device is Android
const isAndroidDevice = (() => {
return Platform.OS === 'android';
})();
// Constants for the download
const MIME_TYPE = 'application/pdf';
const FILE_EXTENSION = 'pdf';
const usePDF = () => {
// Loacal States
const [isLoading, setIsLoading] = useState(false);
const [isDownloadDone, setIsDownloadDone] = useState(false);
const [_pdf, setPdf] = useState<any>(null);
const [path, setPath] = useState('');
const downloadPDF = async ({
url,
method,
fileName,
optionsHeader,
description,
callback,
}: {
url: string;
method: Methods;
fileName: string;
optionsHeader: any;
description?: string;
callback?: (...params: any[]) => void;
}) => {
// Set the path of the file and start the loading
const dirs = ReactNativeBlobUtil.fs.dirs;
const pathFile = `${
isAndroidDevice ? dirs.LegacyDownloadDir : dirs.DocumentDir
}/${fileName}.${FILE_EXTENSION}`;
setPath(pathFile);
setIsLoading(true);
// Congfigurations for the download
const config = {
fileCache: true,
appendExt: FILE_EXTENSION,
path: pathFile,
addAndroidDownloads: {
mime: MIME_TYPE,
title: `${fileName}.${FILE_EXTENSION}`,
description: description || 'PDF File is dowmloaded.',
mediaScannable: true,
notification: true,
},
};
ReactNativeBlobUtil.config(config)
.fetch(method, url, optionsHeader)
.then(res => {
const filePath = res.path();
const fileOptions = {
path: filePath,
mime: MIME_TYPE,
};
if (isAndroidDevice) {
ReactNativeBlobUtil.fs.scanFile([fileOptions]);
} else {
let shareOptions = {
type: MIME_TYPE,
url: filePath,
saveToFiles: true,
};
return Share.open(shareOptions);
}
})
.then(_res => {
// If the file is saved, set the state to true
// and exceute the callback(if it exists)
setIsDownloadDone(true);
callback && callback();
})
.catch(err => {
console.log(err);
})
.finally(() => {
// Finally, set the loading to false
setIsLoading(false);
});
};
return { downloadPDF, isDownloadDone, isLoading, path, setPdf };
};
export default usePDF;
Explanation
There are some things to consider in this hook:
- The hook handles only the downloading of the PDF file. To preview it, you'll need to utilize the react-native-pdf library, which will be explained in more detail beforehand.
- The path of the file is set in the LegacyDownloadDir folder for Android devices and in the DocumentDir folder for iOS devices. This is because the react-native-blob-util library has a different way of handling the download for each platform. So the file easy to find in both platforms, but you can change it if you want. For more information, please check the react-native-blob-util documentation
Functions and States exported
List
- _ downloadPDF: is the function that handles the download of the PDF file. It receives an object with the following parameters:
- url: the url of the file
- method: the method of the request
- fileName: the name of the file (without the .pdf extension)
- optionsHeader: the options of the header
- description: the description of the file that will be displayed on Android devices during the downloading process (optional)
- callback: is a callback function that will be executed upon successful completion.(optional)
- isDownloadDone: is a boolean that indicates if the download is done
- isLoading: is a boolean that indicates if the download is in progress
- path: is the final path of the file
- setPdf: is a function that sets the PDF file (internal usage at rendering)
Usage
Calling the hook
In the file where you want to use the hook, import it and call it:
Components used
The components used in this example (Button and Layout) are from the Etendo UI Library
Downloading the PDF
To download the PDF file, you need to call the downloadPDF function and pass the parameters. In this example, we are using a button to trigger the download:
...
const { downloadPDF, isLoading, isDownloadDone, path, setPdf } = usePDF();
return (
...
<Layout
children={
<Button
typeStyle="terciary"
text="Download PDF"
width={200}
onPress={() =>
downloadPDF({
url: `https://your-url.com/your-pdf-file.pdf`,
method: 'GET',
fileName: 'fileNameOfPDF',
optionsHeader: {
'Content-Type': 'application/json',
},
description: 'File description',
})
}
loading={isLoading}
/>
}
/>
);
This will be displayed as follows:
Previewing the PDF
To preview the PDF file, you need to use the react-native-pdf library. Following the example above, you can use the path state to set the source of the PDF file and the setPdf function to set the PDF file:
...
<View style={styles.container}>
<Pdf
ref={pdf => {
setPdf(pdf);
}}
source={
isDownloadDone && {
uri: path,
}
}
style={styles.pdf}
/>
</View>
Styles used
The styles used in this example (container and pdf) are the following:
...
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'center',
height,
width,
alignItems: 'center',
marginTop: 25,
backgroundColor: 'red',
},
pdf: {
flex: 1,
width,
height,
},
});
After save, the final result, you should see something like this: