A library that provides printing functionality for Android and iOS (AirPrint).
GitHub
npm
expo-print
provides an API for Android and iOS (AirPrint) printing functionality.
-
npx expo install expo-print
If you are installing this in an existing React Native app (bare workflow), start by installing expo
in your project. Then, follow the additional instructions as mentioned by library's README under "Installation in bare React Native projects" section.
import { useState } from 'react';
import { View, StyleSheet, Button, Platform, Text } from 'react-native';
import * as Print from 'expo-print';
import { shareAsync } from 'expo-sharing';
const html = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
</head>
<body style="text-align: center;">
<h1 style="font-size: 50px; font-family: Helvetica Neue; font-weight: normal;">
Hello Expo!
</h1>
<img
src="https://d30j33t1r58ioz.cloudfront.net/static/guides/sdk.png"
style="width: 90vw;" />
</body>
</html>
`;
export default function App() {
const [selectedPrinter, setSelectedPrinter] = useState();
const print = async () => {
// On iOS/android prints the given html. On web prints the HTML from the current page.
await Print.printAsync({
html,
printerUrl: selectedPrinter?.url, // iOS only
});
};
const printToFile = async () => {
// On iOS/android prints the given html. On web prints the HTML from the current page.
const { uri } = await Print.printToFileAsync({ html });
console.log('File has been saved to:', uri);
await shareAsync(uri, { UTI: '.pdf', mimeType: 'application/pdf' });
};
const selectPrinter = async () => {
const printer = await Print.selectPrinterAsync(); // iOS only
setSelectedPrinter(printer);
};
return (
<View style={styles.container}>
<Button title="Print" onPress={print} />
<View style={styles.spacer} />
<Button title="Print to PDF file" onPress={printToFile} />
{Platform.OS === 'ios' && (
<>
<View style={styles.spacer} />
<Button title="Select printer" onPress={selectPrinter} />
<View style={styles.spacer} />
{selectedPrinter ? (
<Text style={styles.printer}>{`Selected printer: ${selectedPrinter.name}`}</Text>
) : undefined}
</>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
flexDirection: 'column',
padding: 8,
},
spacer: {
height: 8,
},
printer: {
textAlign: 'center',
},
});
import * as Print from 'expo-print';
Print.printAsync(options)
Name | Type | Description |
---|---|---|
options | PrintOptions | A map defining what should be printed. |
Prints a document or HTML, on web this prints the HTML from the page.
Note: On iOS, printing from HTML source doesn't support local asset URLs (due to
WKWebView
limitations). As a workaround you can use inlined base64-encoded strings. See this comment for more details.
Note: on iOS, when printing without providing a
PrintOptions.printerUrl
thePromise
will be resolved once printing is started in the native print window and rejected if the window is closed without starting the print. On Android thePromise
will be resolved immediately after displaying the native print window and won't be rejected if the window is closed without starting the print.
Promise<void>
Resolves to an empty Promise
if printing started.
Print.printToFileAsync(options)
Name | Type | Description |
---|---|---|
options (optional) | FilePrintOptions | A map of print options. Default: {} |
Prints HTML to PDF file and saves it to app's cache directory. On Web this method opens the print dialog.
Print.selectPrinterAsync()
Chooses a printer that can be later used in printAsync
A promise which fulfils with an object containing name
and url
of the selected printer.
OrientationType
The possible values of orientation for the printed content.
OrientationType Properties
Name | Type | Description |
---|---|---|
landscape | string | - |
portrait | string | - |
FilePrintOptions
Name | Type | Description |
---|---|---|
base64 (optional) | boolean | Whether to include base64 encoded string of the file in the returned object. |
height (optional) | number | Height of the single page in pixels. Defaults to |
html (optional) | string | HTML string to print into PDF file. |
margins (optional) | PageMargins | Only for: iOS Page margins for the printed document. |
useMarkupFormatter (optional) | boolean | Only for: iOS Alternative to default option that uses UIMarkupTextPrintFormatter instead of WebView, but it doesn't display images. |
width (optional) | number | Width of the single page in pixels. Defaults to |
FilePrintResult
Name | Type | Description |
---|---|---|
base64 (optional) | string | Base64 encoded string containing the data of the PDF file. Available only if |
numberOfPages | number | Number of pages that were needed to render given content. |
uri | string | A URI to the printed PDF file. |
PrintOptions
Name | Type | Description |
---|---|---|
height (optional) | number | Height of the single page in pixels. Defaults to |
html (optional) | string | Only for: Android iOS HTML string to print. |
margins (optional) | PageMargins | Only for: iOS Page margins for the printed document. |
markupFormatterIOS (optional) | string |
Only for: iOS |
orientation (optional) | OrientationType['portrait'] | OrientationType['landscape'] | Only for: iOS The orientation of the printed content, |
printerUrl (optional) | string | Only for: iOS URL of the printer to use. Returned from |
uri (optional) | string | URI of a PDF file to print. Remote, local (ex. selected via |
useMarkupFormatter (optional) | boolean | Only for: iOS Alternative to default option that uses UIMarkupTextPrintFormatter instead of WebView, but it doesn't display images. |
width (optional) | number | Width of the single page in pixels. Defaults to |
Printer
Name | Type | Description |
---|---|---|
name | string | Name of the printer. |
url | string | URL of the printer. |
On iOS, printing from HTML source doesn't support local asset URLs (due to WKWebView limitations). Instead, images need to be converted to base64 and inlined into the HTML.
import { Asset } from 'expo-asset';
import { printAsync } from 'expo-print';
import { manipulateAsync } from 'expo-image-manipulator';
async function generateHTML() {
const asset = Asset.fromModule(require('../../assets/logo.png'));
const image = await manipulateAsync(asset.localUri ?? asset.uri, [], { base64: true });
return `
<html>
<img
src="data:image/jpeg;base64,${image.base64}"
style="width: 90vw;" />
</html>
`;
}
async function print() {
const html = await generateHTML();
await printAsync({ html });
}
On iOS you can set the page margins using the margins
option:
const { uri } = await Print.printToFileAsync({
html: 'This page is printed with margins',
margins: {
left: 20,
top: 50,
right: 20,
bottom: 100,
},
});
If useMarkupFormatter
is set to true
, setting margins may cause a blank page to appear at the end of your printout. To prevent this, make sure your HTML string is a well-formed document, including <!DOCTYPE html>
at the beginning of the string.
On Android, if you're using html
option in printAsync
or printToFileAsync
, the resulting print might contain page margins (it depends on the WebView engine).
They are set by @page
style block and you can override them in your HTML code:
<style>
@page {
margin: 20px;
}
</style>
See @page
documentation on MDN for more details.