Pick arbitrary files through the system document picker
One.DocumentPicker presents the system file picker and returns the
chosen files copied into the app cache. Reach for it for arbitrary
documents, PDFs, archives, or anything outside the photo library; for
camera and library images, the image picker is the better fit.
On iOS it presents UIDocumentPickerViewController opened as a copy. On
Android it fires ACTION_OPEN_DOCUMENT and copies each result to cache.
On web it opens a file dialog and returns blob URLs. No platform needs a
permission for picking.
import { One } from 'one'
const picked = await One.DocumentPicker.getDocument({ type: ['application/pdf', 'image/*'], multiple: false,})if (!picked.canceled) { const [first] = picked.assets console.log(first.uri, first.name, first.mimeType, first.size)}type is one mime type or a list, exact or wildcard, defaulting to
*/*. Backing out resolves { canceled: true, assets: null } instead
of throwing.
Options resolve before any picker opens, identically on every platform:
the type list lowercases and dedupes, multiple defaults to false, and
anything that is not a mime-shaped string or a boolean rejects at once.
On iOS each mime type maps to a UTType for the picker filter; on
Android the list becomes the intent filter; on web it becomes the file
input’s accept string, with */* mapping to an empty accept that offers
every file.
Picked files always land in the app cache as new copies, so the
returned file:// URIs stay readable after the picker closes and need
no persisted security scope. Each asset carries the cached URI, the
display name the provider reported, and the mime type and byte size when
the platform provides them. Read a picked file with fetch(uri):
arrayBuffer, blob, and text all work on both native platforms, so
no file system call is needed to read one. On web the URIs are blob URLs
for the dialog’s files.
One pick runs at a time; a second call while the picker is up rejects.
Runtime failures reject with E_DOCUMENT_PICKER_FAILED.
| Methods | Type | Description |
|---|---|---|
getDocument(options: DocumentPickerOptions) => Promise<DocumentPickerResult>Pick files. Options default to every file, one pick. | (options: DocumentPickerOptions) => Promise<DocumentPickerResult> | Pick files. Options default to every file, one pick. |
| Options | Type | Description |
|---|---|---|
typestring | string[]Mime types to offer, exact or wildcard. Default */*. | string | string[] | Mime types to offer, exact or wildcard. Default */*. |
multiplebooleanAllow more than one file. Default false. | boolean | Allow more than one file. Default false. |
| Picked file | Type | Description |
|---|---|---|
uristringThe cached copy, as a file URI. | string | The cached copy, as a file URI. |
namestringThe display name the provider reported. | string | The display name the provider reported. |
mimeTypestringThe mime type, when the platform provides it. | string | The mime type, when the platform provides it. |
sizenumberSize in bytes of the cached file. | number | Size in bytes of the cached file. |
| Picked result | Type | Description |
|---|---|---|
canceledfalseAlways false on a pick. | false | Always false on a pick. |
assetsDocumentPickerAsset[]The picked files. | DocumentPickerAsset[] | The picked files. |
| Canceled result | Type | Description |
|---|---|---|
canceledtrueAlways true on a cancel. | true | Always true on a cancel. |
assetsnullAlways null on a cancel. | null | Always null on a cancel. |
| iOS | Android | Web | |
|---|---|---|---|
| Picker | System document UI | System document UI | File dialog |
| Results | Cache file URIs | Cache file URIs | Blob URLs |
| Metadata | Name, type, size | Name, type, size | Name, type, size |
| Permission | None needed | None needed | None needed |
canceled: true and null assets. Branch on the flag, not on catch.getDocument while one is open
rejects. Await each pick before offering the next.multiple throws without showing any UI.import { useState } from 'react'import { Button, Text } from 'react-native'import { One } from 'one'
function PdfAttachment({ onAttach }: { onAttach: (uri: string) => void }) { const [name, setName] = useState('')
async function attach() { const picked = await One.DocumentPicker.getDocument({ type: 'application/pdf' }) if (picked.canceled) return const [first] = picked.assets if (!first) return setName(first.name) onAttach(first.uri) }
return ( <> <Button title="Attach a PDF" onPress={attach} /> {name ? <Text>Attached {name}</Text> : null} </> )}The mime filter shows only PDFs, and single-pick mode keeps the result shape simple. The cancel path returns quietly, leaving any previous attachment in place.
import { One } from 'one'
async function readTextFile(): Promise<string | undefined> { const picked = await One.DocumentPicker.getDocument({ type: 'text/*' }) if (picked.canceled) return undefined const [first] = picked.assets if (!first) return undefined return (await fetch(first.uri)).text()}The cached URI is fetchable directly, so small files need no file system API at all. Larger files should stream from the URI instead of loading the whole text at once.
Edit this page on GitHub.