9

I'm using the following code to download a file (can be a PDF or a DOC) and then opening it using Linking.

const { dirs } = RNFetchBlob.fs;
let config = {
    fileCache : true,
    appendExt : extension,
    addAndroidDownloads : {
        useDownloadManager : false,
        notification : false,
        title : 'File',
        description : 'A file.',
        path: `${dirs.DownloadDir}/file.${extension}`,
    },
};
RNFetchBlob.config(config)
    .fetch(
        method,
        remoteUrl,
        APIHelpers.getDefaultHeaders()
    )
    .then((res) => {
        let status = res.info().status;
        if (status == 200) {
            Linking.canOpenURL(res.path())
                .then((supported) => {
                    if (!supported) {
                        alert('Can\'t handle url: ' + res.path());
                    } else {
                        Linking.openURL(res.path())
                            .catch((err) => alert('An error occurred while opening the file. ' + err));
                    }
                })
                .catch((err) => alert('The file cannot be opened. ' + err));
        } else {
            alert('File was not found.')
        }
    })
    .catch((errorMessage, statusCode) => {
        alert('There was some error while downloading the file. ' + errorMessage);
    });

However, I'm getting the following error:

An error occurred while opening the file. Error: Unable to open URL: file:///Users/abhishekpokhriyal/Library/Developer/CoreSimulator/Devices/3E2A9C16-0222-40A6-8C1C-EC174B6EE9E8/data/Containers/Data/Application/A37B9D69-583D-4DC8-94B2-0F4AF8272310/Documents/RNFetchBlob_tmp/RNFetchBlobTmp_o259xexg7axbwq3fh6f4.pdf

I need to implement the solution for both iOS and Android.

Abhishek
  • 153
  • 1
  • 3
  • 15

4 Answers4

4

I think the easiest way to do so is by using react-native-file-viewer package.

It allows you to Prompt the user to choose an app to open the file with (if there are multiple installed apps that support the mimetype).

import FileViewer from 'react-native-file-viewer';

const path = // absolute-path-to-my-local-file.
FileViewer.open(path, { showOpenWithDialog: true })
.then(() => {
    // success
})
.catch(error => {
    // error
});
sangaloma
  • 392
  • 1
  • 3
  • 12
1

So, I finally did this by replacing Linking by the package react-native-file-viewer.

In my APIHelpers.js:

async getRemoteFile(filePath, extension, method = 'GET') {
    const remoteUrl = `${API_BASE_URL}/${encodeURIComponent(filePath)}`;
    const { dirs } = RNFetchBlob.fs;
    let config = {
        fileCache : true,
        appendExt : extension,
        addAndroidDownloads : {
            useDownloadManager : false,
            notification : false,
            title : 'File',
            description : 'A file.',
            path: `${dirs.DownloadDir}/file.${extension}`,
        },
    };

    return new Promise(async (next, error) => {
        try {
            let response = await RNFetchBlob.config(config)
                .fetch(
                    method,
                    remoteUrl,
                    this.getDefaultHeaders()
                );
            next(response);
        } catch (err) {
            error(err);
        }
    });
}

In my Actions.js

export function openDocument(docPath, ext) {
    return async (dispatch) => {
        dispatch(fetchingFile());
        APIHelpers.getRemoteFile(docPath, ext).then(async function(response) {
            dispatch(successFetchingFile());
            let status = response.info().status;
            if (status == 200) {
                const path = response.path();
                setTimeout(() => {
                    FileViewer.open(path, {
                        showOpenWithDialog: true,
                        showAppsSuggestions: true,
                        })
                        .catch(error => {
                            dispatch(errorOpeningFile(error));
                        });
                }, 100);
            } else {
                dispatch(invalidFile());
            }
            }).catch(function(err) {
                dispatch(errorFetchingFile(err));
            });
    }
}

In my Screen.js


import { openDocument } from 'path/to/Actions';

render() {
    return <Button
                title={'View file'}
                onPress={() => this.props.dispatchOpenDocument(doc.filepath, doc.extension)}
            />;
}
.
.
.
const mapDispatchToProps = {
    dispatchOpenDocument: (docPath, ext) => openDocument(docPath, ext),
}

Abhishek
  • 153
  • 1
  • 3
  • 15
0

Are you downloading it from the web? I can see the pdf path is attached at the end of the error path.
For web URLs, the protocol ("http://", "https://") must be set accordingly!

Try to append appropriate schemes to your path. Check it out from the link mentioned below.

Kira
  • 1
0

This can be done with 'rn-fetch-blob'

RNFetchBlob.android.actionViewIntent(fileLocation, mimeType);