I am new to react native and I want to create a mobile version of the the project I made in Ruby on Rails. One part there is in my RoR project it’s easy to generate and download a pdf file. I want also want to do it in a Mobile App. But well it’s not working I’ve been asking a lot of question to my github co-pilot and chatgpt for answers but I can’t still figure it out.
I tested the RoR side since I am much familiar in that side and It generates the pdf file as expected the problem is the mobile app. Whenever I press the button it says it’s successfully downloaded the file but I got prompt or I can’t find the pdf file in the android emulator or even in my phone.
First here’s my rails code:
usersquery_controller.rb
class UsersqueryController < ApplicationController
before_action :authenticate_user!
def download_test
File.delete(Rails.root.join('tmp', 'test.pdf'))
pdf_html = ActionController::Base.new()
pdf_file = WickedPdf.new.pdf_from_string(pdf_html.render_to_string(template: 'usersquery/blank.html.erb', layout: false))
pdf_file_path = Rails.root.join('tmp', 'test.pdf')
File.open(pdf_file_path, 'wb') do |file|
file << pdf_file
end
send_file(pdf_file_path, filename: "test.pdf", type: "application/pdf", disposition: "attachment")
end
end
routes.rb
Rails.application.routes.draw do
mount_devise_token_auth_for 'User', at: 'auth'
get '/download_test', to: 'usersquery#download_test'
end
Then here’s my react native
download.jsx
import React from 'react';
import { View, Button, Alert, Platform } from 'react-native';
import * as FileSystem from 'expo-file-system';
import AsyncStorage from '@react-native-async-storage/async-storage';
import axios from 'axios';
import { encode } from 'base-64';
const getAuthHeaders = async () => {
const accessToken = await AsyncStorage.getItem('accessToken');
const tokenType = await AsyncStorage.getItem('tokenType');
const client = await AsyncStorage.getItem('client');
const expiry = await AsyncStorage.getItem('expiry');
const uid = await AsyncStorage.getItem('uid');
return {
'access-token': accessToken,
'token-type': tokenType,
'client': client,
'expiry': expiry,
'uid': uid,
};
};
const DownloadPDFButton = () => {
const handleDownload = async () => {
try {
const headers = await getAuthHeaders();
const response = await axios.get('http://192.168.0.102:3000/download_test', {
headers: headers,
responseType: 'arraybuffer',
});
const arrayBuffer = response.data;
const base64String = encode(arrayBuffer);
// Determine the directory based on the platform
let directory;
if (Platform.OS === 'android') {
directory = FileSystem.cacheDirectory;
} else if (Platform.OS === 'ios') {
directory = FileSystem.documentDirectory;
}
const fileName = 'test.pdf';
const filePath = `${directory}${fileName}`;
// Download the file directly without sharing
await FileSystem.writeAsStringAsync(filePath, base64String, {
encoding: FileSystem.EncodingType.Base64,
});
Alert.alert(
'PDF Downloaded',
'The PDF has been downloaded to your device.',
[{ text: 'OK', onPress: () => {} }]
);
} catch (error) {
console.error('Error downloading PDF: ', error);
}
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title="Download PDF" onPress={handleDownload} />
</View>
);
};
export default DownloadPDFButton;
Here are the output:
Rails terminal:
enter image description here
Rails tmp folder:
enter image description here
React native Expo go App:
enter image description here
I am expecting a Download prompt in android emulator/phone.
user24720087 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.