expo-document-picker
Version:
Provides access to the system's UI for selecting documents from the available providers on the user's device.
92 lines (81 loc) • 2.68 kB
text/typescript
import { Platform } from 'expo-modules-core';
import { DocumentPickerAsset, DocumentPickerOptions, DocumentPickerResult } from './types';
export default {
async getDocumentAsync({
type = '*/*',
multiple = false,
base64 = false,
}: DocumentPickerOptions): Promise<DocumentPickerResult> {
// SSR guard
if (!Platform.isDOMAvailable) {
return { canceled: true, assets: null };
}
const input = document.createElement('input');
input.style.display = 'none';
input.setAttribute('type', 'file');
input.setAttribute('accept', Array.isArray(type) ? type.join(',') : type);
input.setAttribute('id', String(Math.random()));
if (multiple) {
input.setAttribute('multiple', 'multiple');
}
document.body.appendChild(input);
return new Promise((resolve, reject) => {
input.addEventListener('change', async () => {
if (input.files) {
const results: Promise<DocumentPickerAsset>[] = [];
for (let i = 0; i < input.files.length; i++) {
results.push(readFileAsync(input.files[i], base64));
}
try {
const assets = await Promise.all(results);
resolve({ canceled: false, assets, output: input.files });
} catch (e) {
reject(e);
}
} else {
resolve({ canceled: true, assets: null });
}
document.body.removeChild(input);
});
input.addEventListener('cancel', () => {
resolve({ canceled: true, assets: null });
});
const event = new MouseEvent('click');
input.dispatchEvent(event);
});
},
};
function readFileAsync(targetFile: File, base64: boolean = true): Promise<DocumentPickerAsset> {
return new Promise((resolve, reject) => {
const mimeType = targetFile.type;
if (!base64) {
resolve({
uri: URL.createObjectURL(targetFile),
mimeType,
name: targetFile.name,
lastModified: targetFile.lastModified,
size: targetFile.size,
file: targetFile,
});
return;
}
const reader = new FileReader();
reader.onerror = () => {
reject(new Error(`Failed to read the selected media because the operation failed.`));
};
reader.onload = ({ target }) => {
const base64 = (target as any).result;
resolve({
uri: URL.createObjectURL(targetFile),
base64,
mimeType,
name: targetFile.name,
lastModified: targetFile.lastModified,
size: targetFile.size,
file: targetFile,
});
};
// Read in the image file as a binary string.
reader.readAsDataURL(targetFile);
});
}