18285c032STomasz Sapetaimport { EventEmitter, UnavailabilityError } from 'expo-modules-core'; 21da2f189STomasz Sapetaimport { Platform } from 'react-native'; 37f896a5fSGiau. Tran Minhimport { v4 as uuidv4 } from 'uuid'; 479a5fc63SJames Ideimport ExponentFileSystem from './ExponentFileSystem'; 5*6b7802baSBartosz Kaszubowskiimport { FileSystemSessionType, FileSystemUploadType, } from './FileSystem.types'; 67e929553SEvan Baconif (!ExponentFileSystem) { 72307aaceSEvan Bacon console.warn("No native ExponentFileSystem module found, are you sure the expo-file-system's module is linked properly?"); 82307aaceSEvan Bacon} 98f6e1365SEvan Bacon// Prevent webpack from pruning this. 1079a5fc63SJames Ideconst _unused = new EventEmitter(ExponentFileSystem); // eslint-disable-line 112307aaceSEvan Baconfunction normalizeEndingSlash(p) { 122307aaceSEvan Bacon if (p != null) { 132307aaceSEvan Bacon return p.replace(/\/*$/, '') + '/'; 142307aaceSEvan Bacon } 152307aaceSEvan Bacon return null; 162307aaceSEvan Bacon} 17*6b7802baSBartosz Kaszubowski/** 18*6b7802baSBartosz Kaszubowski * `file://` URI pointing to the directory where user documents for this app will be stored. 19*6b7802baSBartosz Kaszubowski * Files stored here will remain until explicitly deleted by the app. Ends with a trailing `/`. 20*6b7802baSBartosz Kaszubowski * Example uses are for files the user saves that they expect to see again. 21*6b7802baSBartosz Kaszubowski */ 227e929553SEvan Baconexport const documentDirectory = normalizeEndingSlash(ExponentFileSystem.documentDirectory); 23*6b7802baSBartosz Kaszubowski/** 24*6b7802baSBartosz Kaszubowski * `file://` URI pointing to the directory where temporary files used by this app will be stored. 25*6b7802baSBartosz Kaszubowski * Files stored here may be automatically deleted by the system when low on storage. 26*6b7802baSBartosz Kaszubowski * Example uses are for downloaded or generated files that the app just needs for one-time usage. 27*6b7802baSBartosz Kaszubowski */ 287e929553SEvan Baconexport const cacheDirectory = normalizeEndingSlash(ExponentFileSystem.cacheDirectory); 29*6b7802baSBartosz Kaszubowski// @docsMissing 307e929553SEvan Baconexport const { bundledAssets, bundleDirectory } = ExponentFileSystem; 31*6b7802baSBartosz Kaszubowski/** 32*6b7802baSBartosz Kaszubowski * Get metadata information about a file, directory or external content/asset. 33*6b7802baSBartosz Kaszubowski * @param fileUri URI to the file or directory. See [supported URI schemes](#supported-uri-schemes). 34*6b7802baSBartosz Kaszubowski * @param options A map of options represented by [`GetInfoAsyncOptions`](#getinfoasyncoptions) type. 35*6b7802baSBartosz Kaszubowski * @return A Promise that resolves to a `FileInfo` object. If no item exists at this URI, 36*6b7802baSBartosz Kaszubowski * the returned Promise resolves to `FileInfo` object in form of `{ exists: false, isDirectory: false }`. 37*6b7802baSBartosz Kaszubowski */ 382307aaceSEvan Baconexport async function getInfoAsync(fileUri, options = {}) { 397e929553SEvan Bacon if (!ExponentFileSystem.getInfoAsync) { 402307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'getInfoAsync'); 412307aaceSEvan Bacon } 427e929553SEvan Bacon return await ExponentFileSystem.getInfoAsync(fileUri, options); 432307aaceSEvan Bacon} 44*6b7802baSBartosz Kaszubowski/** 45*6b7802baSBartosz Kaszubowski * Read the entire contents of a file as a string. Binary will be returned in raw format, you will need to append `data:image/png;base64,` to use it as Base64. 46*6b7802baSBartosz Kaszubowski * @param fileUri `file://` or [SAF](#saf-uri) URI to the file or directory. 47*6b7802baSBartosz Kaszubowski * @param options A map of read options represented by [`ReadingOptions`](#readingoptions) type. 48*6b7802baSBartosz Kaszubowski * @return A Promise that resolves to a string containing the entire contents of the file. 49*6b7802baSBartosz Kaszubowski */ 50*6b7802baSBartosz Kaszubowskiexport async function readAsStringAsync(fileUri, options = {}) { 517e929553SEvan Bacon if (!ExponentFileSystem.readAsStringAsync) { 522307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'readAsStringAsync'); 532307aaceSEvan Bacon } 54*6b7802baSBartosz Kaszubowski return await ExponentFileSystem.readAsStringAsync(fileUri, options); 552307aaceSEvan Bacon} 56*6b7802baSBartosz Kaszubowski/** 57*6b7802baSBartosz Kaszubowski * Takes a `file://` URI and converts it into content URI (`content://`) so that it can be accessed by other applications outside of Expo. 58*6b7802baSBartosz Kaszubowski * @param fileUri The local URI of the file. If there is no file at this URI, an exception will be thrown. 59*6b7802baSBartosz Kaszubowski * @example 60*6b7802baSBartosz Kaszubowski * ```js 61*6b7802baSBartosz Kaszubowski * FileSystem.getContentUriAsync(uri).then(cUri => { 62*6b7802baSBartosz Kaszubowski * console.log(cUri); 63*6b7802baSBartosz Kaszubowski * IntentLauncher.startActivityAsync('android.intent.action.VIEW', { 64*6b7802baSBartosz Kaszubowski * data: cUri, 65*6b7802baSBartosz Kaszubowski * flags: 1, 66*6b7802baSBartosz Kaszubowski * }); 67*6b7802baSBartosz Kaszubowski * }); 68*6b7802baSBartosz Kaszubowski * ``` 69*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to a `string` containing a `content://` URI pointing to the file. 70*6b7802baSBartosz Kaszubowski * The URI is the same as the `fileUri` input parameter but in a different format. 71*6b7802baSBartosz Kaszubowski */ 72e4897761STongyu Zhuexport async function getContentUriAsync(fileUri) { 731da2f189STomasz Sapeta if (Platform.OS === 'android') { 74e4897761STongyu Zhu if (!ExponentFileSystem.getContentUriAsync) { 75e4897761STongyu Zhu throw new UnavailabilityError('expo-file-system', 'getContentUriAsync'); 76e4897761STongyu Zhu } 77e4897761STongyu Zhu return await ExponentFileSystem.getContentUriAsync(fileUri); 78e4897761STongyu Zhu } 791da2f189STomasz Sapeta else { 801da2f189STomasz Sapeta return new Promise(function (resolve, reject) { 811da2f189STomasz Sapeta resolve(fileUri); 821da2f189STomasz Sapeta }); 831da2f189STomasz Sapeta } 841da2f189STomasz Sapeta} 85*6b7802baSBartosz Kaszubowski/** 86*6b7802baSBartosz Kaszubowski * Write the entire contents of a file as a string. 87*6b7802baSBartosz Kaszubowski * @param fileUri `file://` or [SAF](#saf-uri) URI to the file or directory. 88*6b7802baSBartosz Kaszubowski * > Note: when you're using SAF URI the file needs to exist. You can't create a new file. 89*6b7802baSBartosz Kaszubowski * @param contents The string to replace the contents of the file with. 90*6b7802baSBartosz Kaszubowski * @param options A map of write options represented by [`WritingOptions`](#writingoptions) type. 91*6b7802baSBartosz Kaszubowski */ 922307aaceSEvan Baconexport async function writeAsStringAsync(fileUri, contents, options = {}) { 937e929553SEvan Bacon if (!ExponentFileSystem.writeAsStringAsync) { 942307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'writeAsStringAsync'); 952307aaceSEvan Bacon } 967e929553SEvan Bacon return await ExponentFileSystem.writeAsStringAsync(fileUri, contents, options); 972307aaceSEvan Bacon} 98*6b7802baSBartosz Kaszubowski/** 99*6b7802baSBartosz Kaszubowski * Delete a file or directory. If the URI points to a directory, the directory and all its contents are recursively deleted. 100*6b7802baSBartosz Kaszubowski * @param fileUri `file://` or [SAF](#saf-uri) URI to the file or directory. 101*6b7802baSBartosz Kaszubowski * @param options A map of write options represented by [`DeletingOptions`](#deletingoptions) type. 102*6b7802baSBartosz Kaszubowski */ 1032307aaceSEvan Baconexport async function deleteAsync(fileUri, options = {}) { 1047e929553SEvan Bacon if (!ExponentFileSystem.deleteAsync) { 1052307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'deleteAsync'); 1062307aaceSEvan Bacon } 1077e929553SEvan Bacon return await ExponentFileSystem.deleteAsync(fileUri, options); 1082307aaceSEvan Bacon} 1090d6db115SEric Samelsonexport async function deleteLegacyDocumentDirectoryAndroid() { 1100d6db115SEric Samelson if (Platform.OS !== 'android' || documentDirectory == null) { 1110d6db115SEric Samelson return; 1120d6db115SEric Samelson } 1130d6db115SEric Samelson const legacyDocumentDirectory = `${documentDirectory}ExperienceData/`; 1140d6db115SEric Samelson return await deleteAsync(legacyDocumentDirectory, { idempotent: true }); 1150d6db115SEric Samelson} 116*6b7802baSBartosz Kaszubowski/** 117*6b7802baSBartosz Kaszubowski * Move a file or directory to a new location. 118*6b7802baSBartosz Kaszubowski * @param options A map of move options represented by [`RelocatingOptions`](#relocatingoptions) type. 119*6b7802baSBartosz Kaszubowski */ 1202307aaceSEvan Baconexport async function moveAsync(options) { 1217e929553SEvan Bacon if (!ExponentFileSystem.moveAsync) { 1222307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'moveAsync'); 1232307aaceSEvan Bacon } 1247e929553SEvan Bacon return await ExponentFileSystem.moveAsync(options); 1252307aaceSEvan Bacon} 126*6b7802baSBartosz Kaszubowski/** 127*6b7802baSBartosz Kaszubowski * Create a copy of a file or directory. Directories are recursively copied with all of their contents. 128*6b7802baSBartosz Kaszubowski * It can be also used to copy content shared by other apps to local filesystem. 129*6b7802baSBartosz Kaszubowski * @param options A map of move options represented by [`RelocatingOptions`](#relocatingoptions) type. 130*6b7802baSBartosz Kaszubowski */ 1312307aaceSEvan Baconexport async function copyAsync(options) { 1327e929553SEvan Bacon if (!ExponentFileSystem.copyAsync) { 1332307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'copyAsync'); 1342307aaceSEvan Bacon } 1357e929553SEvan Bacon return await ExponentFileSystem.copyAsync(options); 1362307aaceSEvan Bacon} 137*6b7802baSBartosz Kaszubowski/** 138*6b7802baSBartosz Kaszubowski * Create a new empty directory. 139*6b7802baSBartosz Kaszubowski * @param fileUri `file://` URI to the new directory to create. 140*6b7802baSBartosz Kaszubowski * @param options A map of create directory options represented by [`MakeDirectoryOptions`](#makedirectoryoptions) type. 141*6b7802baSBartosz Kaszubowski */ 1422307aaceSEvan Baconexport async function makeDirectoryAsync(fileUri, options = {}) { 1437e929553SEvan Bacon if (!ExponentFileSystem.makeDirectoryAsync) { 1442307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'makeDirectoryAsync'); 1452307aaceSEvan Bacon } 1467e929553SEvan Bacon return await ExponentFileSystem.makeDirectoryAsync(fileUri, options); 1472307aaceSEvan Bacon} 148*6b7802baSBartosz Kaszubowski/** 149*6b7802baSBartosz Kaszubowski * Enumerate the contents of a directory. 150*6b7802baSBartosz Kaszubowski * @param fileUri `file://` URI to the directory. 151*6b7802baSBartosz Kaszubowski * @return A Promise that resolves to an array of strings, each containing the name of a file or directory contained in the directory at `fileUri`. 152*6b7802baSBartosz Kaszubowski */ 1532307aaceSEvan Baconexport async function readDirectoryAsync(fileUri) { 1547e929553SEvan Bacon if (!ExponentFileSystem.readDirectoryAsync) { 1552307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'readDirectoryAsync'); 1562307aaceSEvan Bacon } 1577e929553SEvan Bacon return await ExponentFileSystem.readDirectoryAsync(fileUri, {}); 1582307aaceSEvan Bacon} 159*6b7802baSBartosz Kaszubowski/** 160*6b7802baSBartosz Kaszubowski * Gets the available internal disk storage size, in bytes. This returns the free space on the data partition that hosts all of the internal storage for all apps on the device. 161*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to the number of bytes available on the internal disk, or JavaScript's [`MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) 162*6b7802baSBartosz Kaszubowski * if the capacity is greater than 2<sup>53</sup> - 1 bytes. 163*6b7802baSBartosz Kaszubowski */ 164ae9a5f1aSTongyu Zhuexport async function getFreeDiskStorageAsync() { 165ae9a5f1aSTongyu Zhu if (!ExponentFileSystem.getFreeDiskStorageAsync) { 166ae9a5f1aSTongyu Zhu throw new UnavailabilityError('expo-file-system', 'getFreeDiskStorageAsync'); 167ae9a5f1aSTongyu Zhu } 168ae9a5f1aSTongyu Zhu return await ExponentFileSystem.getFreeDiskStorageAsync(); 169ae9a5f1aSTongyu Zhu} 170*6b7802baSBartosz Kaszubowski/** 171*6b7802baSBartosz Kaszubowski * Gets total internal disk storage size, in bytes. This is the total capacity of the data partition that hosts all the internal storage for all apps on the device. 172*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to a number that specifies the total internal disk storage capacity in bytes, or JavaScript's [`MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) 173*6b7802baSBartosz Kaszubowski * if the capacity is greater than 2<sup>53</sup> - 1 bytes. 174*6b7802baSBartosz Kaszubowski */ 175ae9a5f1aSTongyu Zhuexport async function getTotalDiskCapacityAsync() { 176ae9a5f1aSTongyu Zhu if (!ExponentFileSystem.getTotalDiskCapacityAsync) { 177ae9a5f1aSTongyu Zhu throw new UnavailabilityError('expo-file-system', 'getTotalDiskCapacityAsync'); 178ae9a5f1aSTongyu Zhu } 179ae9a5f1aSTongyu Zhu return await ExponentFileSystem.getTotalDiskCapacityAsync(); 180ae9a5f1aSTongyu Zhu} 181*6b7802baSBartosz Kaszubowski/** 182*6b7802baSBartosz Kaszubowski * Download the contents at a remote URI to a file in the app's file system. The directory for a local file uri must exist prior to calling this function. 183*6b7802baSBartosz Kaszubowski * @param uri The remote URI to download from. 184*6b7802baSBartosz Kaszubowski * @param fileUri The local URI of the file to download to. If there is no file at this URI, a new one is created. 185*6b7802baSBartosz Kaszubowski * If there is a file at this URI, its contents are replaced. The directory for the file must exist. 186*6b7802baSBartosz Kaszubowski * @param options A map of download options represented by [`DownloadOptions`](#downloadoptions) type. 187*6b7802baSBartosz Kaszubowski * @example 188*6b7802baSBartosz Kaszubowski * ```js 189*6b7802baSBartosz Kaszubowski * FileSystem.downloadAsync( 190*6b7802baSBartosz Kaszubowski * 'http://techslides.com/demos/sample-videos/small.mp4', 191*6b7802baSBartosz Kaszubowski * FileSystem.documentDirectory + 'small.mp4' 192*6b7802baSBartosz Kaszubowski * ) 193*6b7802baSBartosz Kaszubowski * .then(({ uri }) => { 194*6b7802baSBartosz Kaszubowski * console.log('Finished downloading to ', uri); 195*6b7802baSBartosz Kaszubowski * }) 196*6b7802baSBartosz Kaszubowski * .catch(error => { 197*6b7802baSBartosz Kaszubowski * console.error(error); 198*6b7802baSBartosz Kaszubowski * }); 199*6b7802baSBartosz Kaszubowski * ``` 200*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to a `FileSystemDownloadResult` object. 201*6b7802baSBartosz Kaszubowski */ 2022307aaceSEvan Baconexport async function downloadAsync(uri, fileUri, options = {}) { 2037e929553SEvan Bacon if (!ExponentFileSystem.downloadAsync) { 2042307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'downloadAsync'); 2052307aaceSEvan Bacon } 206da65a760SŁukasz Kosmaty return await ExponentFileSystem.downloadAsync(uri, fileUri, { 207da65a760SŁukasz Kosmaty sessionType: FileSystemSessionType.BACKGROUND, 208da65a760SŁukasz Kosmaty ...options, 209da65a760SŁukasz Kosmaty }); 210da65a760SŁukasz Kosmaty} 211*6b7802baSBartosz Kaszubowski/** 212*6b7802baSBartosz Kaszubowski * Upload the contents of the file pointed by `fileUri` to the remote url. 213*6b7802baSBartosz Kaszubowski * @param url The remote URL, where the file will be sent. 214*6b7802baSBartosz Kaszubowski * @param fileUri The local URI of the file to send. The file must exist. 215*6b7802baSBartosz Kaszubowski * @param options A map of download options represented by [`FileSystemUploadOptions`](#filesystemuploadoptions) type. 216*6b7802baSBartosz Kaszubowski * @example 217*6b7802baSBartosz Kaszubowski * **Client** 218*6b7802baSBartosz Kaszubowski * 219*6b7802baSBartosz Kaszubowski * ```js 220*6b7802baSBartosz Kaszubowski * import * as FileSystem from 'expo-file-system'; 221*6b7802baSBartosz Kaszubowski * 222*6b7802baSBartosz Kaszubowski * try { 223*6b7802baSBartosz Kaszubowski * const response = await FileSystem.uploadAsync(`http://192.168.0.1:1234/binary-upload`, fileUri, { 224*6b7802baSBartosz Kaszubowski * fieldName: 'file', 225*6b7802baSBartosz Kaszubowski * httpMethod: 'PATCH', 226*6b7802baSBartosz Kaszubowski * uploadType: FileSystem.FileSystemUploadType.BINARY_CONTENT, 227*6b7802baSBartosz Kaszubowski * }); 228*6b7802baSBartosz Kaszubowski * console.log(JSON.stringify(response, null, 4)); 229*6b7802baSBartosz Kaszubowski * } catch (error) { 230*6b7802baSBartosz Kaszubowski * console.log(error); 231*6b7802baSBartosz Kaszubowski * } 232*6b7802baSBartosz Kaszubowski * ``` 233*6b7802baSBartosz Kaszubowski * 234*6b7802baSBartosz Kaszubowski * **Server** 235*6b7802baSBartosz Kaszubowski * 236*6b7802baSBartosz Kaszubowski * Please refer to the "[Server: Handling multipart requests](#server-handling-multipart-requests)" example - there is code for a simple Node.js server. 237*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to `FileSystemUploadResult` object. 238*6b7802baSBartosz Kaszubowski */ 239da65a760SŁukasz Kosmatyexport async function uploadAsync(url, fileUri, options = {}) { 240da65a760SŁukasz Kosmaty if (!ExponentFileSystem.uploadAsync) { 241da65a760SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'uploadAsync'); 242da65a760SŁukasz Kosmaty } 243da65a760SŁukasz Kosmaty return await ExponentFileSystem.uploadAsync(url, fileUri, { 244da65a760SŁukasz Kosmaty sessionType: FileSystemSessionType.BACKGROUND, 24537630a92SŁukasz Kosmaty uploadType: FileSystemUploadType.BINARY_CONTENT, 246da65a760SŁukasz Kosmaty ...options, 247da65a760SŁukasz Kosmaty httpMethod: (options.httpMethod || 'POST').toUpperCase(), 248da65a760SŁukasz Kosmaty }); 2492307aaceSEvan Bacon} 250*6b7802baSBartosz Kaszubowski/** 251*6b7802baSBartosz Kaszubowski * Create a `DownloadResumable` object which can start, pause, and resume a download of contents at a remote URI to a file in the app's file system. 252*6b7802baSBartosz Kaszubowski * > Note: You need to call `downloadAsync()`, on a `DownloadResumable` instance to initiate the download. 253*6b7802baSBartosz Kaszubowski * The `DownloadResumable` object has a callback that provides download progress updates. 254*6b7802baSBartosz Kaszubowski * Downloads can be resumed across app restarts by using `AsyncStorage` to store the `DownloadResumable.savable()` object for later retrieval. 255*6b7802baSBartosz Kaszubowski * The `savable` object contains the arguments required to initialize a new `DownloadResumable` object to resume the download after an app restart. 256*6b7802baSBartosz Kaszubowski * The directory for a local file uri must exist prior to calling this function. 257*6b7802baSBartosz Kaszubowski * @param uri The remote URI to download from. 258*6b7802baSBartosz Kaszubowski * @param fileUri The local URI of the file to download to. If there is no file at this URI, a new one is created. 259*6b7802baSBartosz Kaszubowski * If there is a file at this URI, its contents are replaced. The directory for the file must exist. 260*6b7802baSBartosz Kaszubowski * @param options A map of download options represented by [`DownloadOptions`](#downloadoptions) type. 261*6b7802baSBartosz Kaszubowski * @param callback This function is called on each data write to update the download progress. 262*6b7802baSBartosz Kaszubowski * > **Note**: When the app has been moved to the background, this callback won't be fired until it's moved to the foreground. 263*6b7802baSBartosz Kaszubowski * @param resumeData The string which allows the api to resume a paused download. This is set on the `DownloadResumable` object automatically when a download is paused. 264*6b7802baSBartosz Kaszubowski * When initializing a new `DownloadResumable` this should be `null`. 265*6b7802baSBartosz Kaszubowski */ 2662307aaceSEvan Baconexport function createDownloadResumable(uri, fileUri, options, callback, resumeData) { 2672307aaceSEvan Bacon return new DownloadResumable(uri, fileUri, options, callback, resumeData); 2682307aaceSEvan Bacon} 26952eeb172SŁukasz Kosmatyexport function createUploadTask(url, fileUri, options, callback) { 27052eeb172SŁukasz Kosmaty return new UploadTask(url, fileUri, options, callback); 27152eeb172SŁukasz Kosmaty} 27252eeb172SŁukasz Kosmatyexport class FileSystemCancellableNetworkTask { 27352eeb172SŁukasz Kosmaty _uuid = uuidv4(); 27452eeb172SŁukasz Kosmaty taskWasCanceled = false; 27552eeb172SŁukasz Kosmaty emitter = new EventEmitter(ExponentFileSystem); 27652eeb172SŁukasz Kosmaty subscription; 277*6b7802baSBartosz Kaszubowski // @docsMissing 27852eeb172SŁukasz Kosmaty async cancelAsync() { 27952eeb172SŁukasz Kosmaty if (!ExponentFileSystem.networkTaskCancelAsync) { 28052eeb172SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'networkTaskCancelAsync'); 28152eeb172SŁukasz Kosmaty } 28252eeb172SŁukasz Kosmaty this.removeSubscription(); 28352eeb172SŁukasz Kosmaty this.taskWasCanceled = true; 28452eeb172SŁukasz Kosmaty return await ExponentFileSystem.networkTaskCancelAsync(this.uuid); 28552eeb172SŁukasz Kosmaty } 28652eeb172SŁukasz Kosmaty isTaskCancelled() { 28752eeb172SŁukasz Kosmaty if (this.taskWasCanceled) { 28852eeb172SŁukasz Kosmaty console.warn('This task was already canceled.'); 28952eeb172SŁukasz Kosmaty return true; 29052eeb172SŁukasz Kosmaty } 29152eeb172SŁukasz Kosmaty return false; 29252eeb172SŁukasz Kosmaty } 29352eeb172SŁukasz Kosmaty get uuid() { 29452eeb172SŁukasz Kosmaty return this._uuid; 29552eeb172SŁukasz Kosmaty } 29652eeb172SŁukasz Kosmaty addSubscription() { 29752eeb172SŁukasz Kosmaty if (this.subscription) { 29852eeb172SŁukasz Kosmaty return; 29952eeb172SŁukasz Kosmaty } 30052eeb172SŁukasz Kosmaty this.subscription = this.emitter.addListener(this.getEventName(), (event) => { 30152eeb172SŁukasz Kosmaty if (event.uuid === this.uuid) { 30252eeb172SŁukasz Kosmaty const callback = this.getCallback(); 30352eeb172SŁukasz Kosmaty if (callback) { 30452eeb172SŁukasz Kosmaty callback(event.data); 30552eeb172SŁukasz Kosmaty } 30652eeb172SŁukasz Kosmaty } 30752eeb172SŁukasz Kosmaty }); 30852eeb172SŁukasz Kosmaty } 30952eeb172SŁukasz Kosmaty removeSubscription() { 31052eeb172SŁukasz Kosmaty if (!this.subscription) { 31152eeb172SŁukasz Kosmaty return; 31252eeb172SŁukasz Kosmaty } 31352eeb172SŁukasz Kosmaty this.emitter.removeSubscription(this.subscription); 31452eeb172SŁukasz Kosmaty this.subscription = null; 31552eeb172SŁukasz Kosmaty } 31652eeb172SŁukasz Kosmaty} 31752eeb172SŁukasz Kosmatyexport class UploadTask extends FileSystemCancellableNetworkTask { 31852eeb172SŁukasz Kosmaty url; 31952eeb172SŁukasz Kosmaty fileUri; 32052eeb172SŁukasz Kosmaty callback; 32152eeb172SŁukasz Kosmaty options; 32252eeb172SŁukasz Kosmaty constructor(url, fileUri, options, callback) { 32352eeb172SŁukasz Kosmaty super(); 32452eeb172SŁukasz Kosmaty this.url = url; 32552eeb172SŁukasz Kosmaty this.fileUri = fileUri; 32652eeb172SŁukasz Kosmaty this.callback = callback; 32700d910e2SLuke Brandon Farrell const httpMethod = (options?.httpMethod?.toUpperCase() || 32852eeb172SŁukasz Kosmaty 'POST'); 32952eeb172SŁukasz Kosmaty this.options = { 33052eeb172SŁukasz Kosmaty sessionType: FileSystemSessionType.BACKGROUND, 33152eeb172SŁukasz Kosmaty uploadType: FileSystemUploadType.BINARY_CONTENT, 33252eeb172SŁukasz Kosmaty ...options, 33352eeb172SŁukasz Kosmaty httpMethod, 33452eeb172SŁukasz Kosmaty }; 33552eeb172SŁukasz Kosmaty } 33652eeb172SŁukasz Kosmaty getEventName() { 33752eeb172SŁukasz Kosmaty return 'expo-file-system.uploadProgress'; 33852eeb172SŁukasz Kosmaty } 33952eeb172SŁukasz Kosmaty getCallback() { 34052eeb172SŁukasz Kosmaty return this.callback; 34152eeb172SŁukasz Kosmaty } 342*6b7802baSBartosz Kaszubowski // @docsMissing 34352eeb172SŁukasz Kosmaty async uploadAsync() { 34452eeb172SŁukasz Kosmaty if (!ExponentFileSystem.uploadTaskStartAsync) { 34552eeb172SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'uploadTaskStartAsync'); 34652eeb172SŁukasz Kosmaty } 34752eeb172SŁukasz Kosmaty if (this.isTaskCancelled()) { 34852eeb172SŁukasz Kosmaty return; 34952eeb172SŁukasz Kosmaty } 35052eeb172SŁukasz Kosmaty this.addSubscription(); 35152eeb172SŁukasz Kosmaty const result = await ExponentFileSystem.uploadTaskStartAsync(this.url, this.fileUri, this.uuid, this.options); 35252eeb172SŁukasz Kosmaty this.removeSubscription(); 35352eeb172SŁukasz Kosmaty return result; 35452eeb172SŁukasz Kosmaty } 35552eeb172SŁukasz Kosmaty} 35652eeb172SŁukasz Kosmatyexport class DownloadResumable extends FileSystemCancellableNetworkTask { 35752eeb172SŁukasz Kosmaty url; 358896103abSandy _fileUri; 35952eeb172SŁukasz Kosmaty options; 36052eeb172SŁukasz Kosmaty callback; 36152eeb172SŁukasz Kosmaty resumeData; 36252eeb172SŁukasz Kosmaty constructor(url, _fileUri, options = {}, callback, resumeData) { 36352eeb172SŁukasz Kosmaty super(); 36452eeb172SŁukasz Kosmaty this.url = url; 36552eeb172SŁukasz Kosmaty this._fileUri = _fileUri; 36652eeb172SŁukasz Kosmaty this.options = options; 36752eeb172SŁukasz Kosmaty this.callback = callback; 36852eeb172SŁukasz Kosmaty this.resumeData = resumeData; 36952eeb172SŁukasz Kosmaty } 37052eeb172SŁukasz Kosmaty get fileUri() { 37152eeb172SŁukasz Kosmaty return this._fileUri; 37252eeb172SŁukasz Kosmaty } 37352eeb172SŁukasz Kosmaty getEventName() { 37452eeb172SŁukasz Kosmaty return 'expo-file-system.downloadProgress'; 37552eeb172SŁukasz Kosmaty } 37652eeb172SŁukasz Kosmaty getCallback() { 37752eeb172SŁukasz Kosmaty return this.callback; 3782307aaceSEvan Bacon } 379*6b7802baSBartosz Kaszubowski /** 380*6b7802baSBartosz Kaszubowski * Download the contents at a remote URI to a file in the app's file system. 381*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to `FileSystemDownloadResult` object, or to `undefined` when task was cancelled. 382*6b7802baSBartosz Kaszubowski */ 3832307aaceSEvan Bacon async downloadAsync() { 3847e929553SEvan Bacon if (!ExponentFileSystem.downloadResumableStartAsync) { 3852307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'downloadResumableStartAsync'); 3862307aaceSEvan Bacon } 38752eeb172SŁukasz Kosmaty if (this.isTaskCancelled()) { 38852eeb172SŁukasz Kosmaty return; 38952eeb172SŁukasz Kosmaty } 39052eeb172SŁukasz Kosmaty this.addSubscription(); 39152eeb172SŁukasz Kosmaty return await ExponentFileSystem.downloadResumableStartAsync(this.url, this._fileUri, this.uuid, this.options, this.resumeData); 3922307aaceSEvan Bacon } 393*6b7802baSBartosz Kaszubowski /** 394*6b7802baSBartosz Kaszubowski * Pause the current download operation. `resumeData` is added to the `DownloadResumable` object after a successful pause operation. 395*6b7802baSBartosz Kaszubowski * Returns an object that can be saved with `AsyncStorage` for future retrieval (the same object that is returned from calling `FileSystem.DownloadResumable.savable()`). 396*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to `DownloadPauseState` object. 397*6b7802baSBartosz Kaszubowski */ 3982307aaceSEvan Bacon async pauseAsync() { 3997e929553SEvan Bacon if (!ExponentFileSystem.downloadResumablePauseAsync) { 4002307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'downloadResumablePauseAsync'); 4012307aaceSEvan Bacon } 40252eeb172SŁukasz Kosmaty if (this.isTaskCancelled()) { 40352eeb172SŁukasz Kosmaty return { 40452eeb172SŁukasz Kosmaty fileUri: this._fileUri, 40552eeb172SŁukasz Kosmaty options: this.options, 40652eeb172SŁukasz Kosmaty url: this.url, 40752eeb172SŁukasz Kosmaty }; 40852eeb172SŁukasz Kosmaty } 40952eeb172SŁukasz Kosmaty const pauseResult = await ExponentFileSystem.downloadResumablePauseAsync(this.uuid); 41052eeb172SŁukasz Kosmaty this.removeSubscription(); 4112307aaceSEvan Bacon if (pauseResult) { 41252eeb172SŁukasz Kosmaty this.resumeData = pauseResult.resumeData; 4132307aaceSEvan Bacon return this.savable(); 4142307aaceSEvan Bacon } 4152307aaceSEvan Bacon else { 4162307aaceSEvan Bacon throw new Error('Unable to generate a savable pause state'); 4172307aaceSEvan Bacon } 4182307aaceSEvan Bacon } 419*6b7802baSBartosz Kaszubowski /** 420*6b7802baSBartosz Kaszubowski * Resume a paused download operation. 421*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to `FileSystemDownloadResult` object, or to `undefined` when task was cancelled. 422*6b7802baSBartosz Kaszubowski */ 4232307aaceSEvan Bacon async resumeAsync() { 4247e929553SEvan Bacon if (!ExponentFileSystem.downloadResumableStartAsync) { 4252307aaceSEvan Bacon throw new UnavailabilityError('expo-file-system', 'downloadResumableStartAsync'); 4262307aaceSEvan Bacon } 42752eeb172SŁukasz Kosmaty if (this.isTaskCancelled()) { 42852eeb172SŁukasz Kosmaty return; 42952eeb172SŁukasz Kosmaty } 43052eeb172SŁukasz Kosmaty this.addSubscription(); 43152eeb172SŁukasz Kosmaty return await ExponentFileSystem.downloadResumableStartAsync(this.url, this.fileUri, this.uuid, this.options, this.resumeData); 4322307aaceSEvan Bacon } 433*6b7802baSBartosz Kaszubowski /** 434*6b7802baSBartosz Kaszubowski * Method to get the object which can be saved with `AsyncStorage` for future retrieval. 435*6b7802baSBartosz Kaszubowski * @returns Returns object in shape of `DownloadPauseState` type. 436*6b7802baSBartosz Kaszubowski */ 4372307aaceSEvan Bacon savable() { 4382307aaceSEvan Bacon return { 43952eeb172SŁukasz Kosmaty url: this.url, 44052eeb172SŁukasz Kosmaty fileUri: this.fileUri, 44152eeb172SŁukasz Kosmaty options: this.options, 44252eeb172SŁukasz Kosmaty resumeData: this.resumeData, 4432307aaceSEvan Bacon }; 4442307aaceSEvan Bacon } 4452307aaceSEvan Bacon} 446400de723SŁukasz Kosmatyconst baseReadAsStringAsync = readAsStringAsync; 447400de723SŁukasz Kosmatyconst baseWriteAsStringAsync = writeAsStringAsync; 448400de723SŁukasz Kosmatyconst baseDeleteAsync = deleteAsync; 449400de723SŁukasz Kosmatyconst baseMoveAsync = moveAsync; 450400de723SŁukasz Kosmatyconst baseCopyAsync = copyAsync; 451400de723SŁukasz Kosmaty/** 452*6b7802baSBartosz Kaszubowski * The `StorageAccessFramework` is a namespace inside of the `expo-file-system` module, which encapsulates all functions which can be used with [SAF URIs](#saf-uri). 453*6b7802baSBartosz Kaszubowski * You can read more about SAF in the [Android documentation](https://developer.android.com/guide/topics/providers/document-provider). 454*6b7802baSBartosz Kaszubowski * 455*6b7802baSBartosz Kaszubowski * @example 456*6b7802baSBartosz Kaszubowski * # Basic Usage 457*6b7802baSBartosz Kaszubowski * 458*6b7802baSBartosz Kaszubowski * ```ts 459*6b7802baSBartosz Kaszubowski * import { StorageAccessFramework } from 'expo-file-system'; 460*6b7802baSBartosz Kaszubowski * 461*6b7802baSBartosz Kaszubowski * // Requests permissions for external directory 462*6b7802baSBartosz Kaszubowski * const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(); 463*6b7802baSBartosz Kaszubowski * 464*6b7802baSBartosz Kaszubowski * if (permissions.granted) { 465*6b7802baSBartosz Kaszubowski * // Gets SAF URI from response 466*6b7802baSBartosz Kaszubowski * const uri = permissions.directoryUri; 467*6b7802baSBartosz Kaszubowski * 468*6b7802baSBartosz Kaszubowski * // Gets all files inside of selected directory 469*6b7802baSBartosz Kaszubowski * const files = await StorageAccessFramework.readDirectoryAsync(uri); 470*6b7802baSBartosz Kaszubowski * alert(`Files inside ${uri}:\n\n${JSON.stringify(files)}`); 471*6b7802baSBartosz Kaszubowski * } 472*6b7802baSBartosz Kaszubowski * ``` 473*6b7802baSBartosz Kaszubowski * 474*6b7802baSBartosz Kaszubowski * # Migrating an album 475*6b7802baSBartosz Kaszubowski * 476*6b7802baSBartosz Kaszubowski * ```ts 477*6b7802baSBartosz Kaszubowski * import * as MediaLibrary from 'expo-media-library'; 478*6b7802baSBartosz Kaszubowski * import * as FileSystem from 'expo-file-system'; 479*6b7802baSBartosz Kaszubowski * const { StorageAccessFramework } = FileSystem; 480*6b7802baSBartosz Kaszubowski * 481*6b7802baSBartosz Kaszubowski * async function migrateAlbum(albumName: string) { 482*6b7802baSBartosz Kaszubowski * // Gets SAF URI to the album 483*6b7802baSBartosz Kaszubowski * const albumUri = StorageAccessFramework.getUriForDirectoryInRoot(albumName); 484*6b7802baSBartosz Kaszubowski * 485*6b7802baSBartosz Kaszubowski * // Requests permissions 486*6b7802baSBartosz Kaszubowski * const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(albumUri); 487*6b7802baSBartosz Kaszubowski * if (!permissions.granted) { 488*6b7802baSBartosz Kaszubowski * return; 489*6b7802baSBartosz Kaszubowski * } 490*6b7802baSBartosz Kaszubowski * 491*6b7802baSBartosz Kaszubowski * const permittedUri = permissions.directoryUri; 492*6b7802baSBartosz Kaszubowski * // Checks if users selected the correct folder 493*6b7802baSBartosz Kaszubowski * if (!permittedUri.includes(albumName)) { 494*6b7802baSBartosz Kaszubowski * return; 495*6b7802baSBartosz Kaszubowski * } 496*6b7802baSBartosz Kaszubowski * 497*6b7802baSBartosz Kaszubowski * const mediaLibraryPermissions = await MediaLibrary.requestPermissionsAsync(); 498*6b7802baSBartosz Kaszubowski * if (!mediaLibraryPermissions.granted) { 499*6b7802baSBartosz Kaszubowski * return; 500*6b7802baSBartosz Kaszubowski * } 501*6b7802baSBartosz Kaszubowski * 502*6b7802baSBartosz Kaszubowski * // Moves files from external storage to internal storage 503*6b7802baSBartosz Kaszubowski * await StorageAccessFramework.moveAsync({ 504*6b7802baSBartosz Kaszubowski * from: permittedUri, 505*6b7802baSBartosz Kaszubowski * to: FileSystem.documentDirectory!, 506*6b7802baSBartosz Kaszubowski * }); 507*6b7802baSBartosz Kaszubowski * 508*6b7802baSBartosz Kaszubowski * const outputDir = FileSystem.documentDirectory! + albumName; 509*6b7802baSBartosz Kaszubowski * const migratedFiles = await FileSystem.readDirectoryAsync(outputDir); 510*6b7802baSBartosz Kaszubowski * 511*6b7802baSBartosz Kaszubowski * // Creates assets from local files 512*6b7802baSBartosz Kaszubowski * const [newAlbumCreator, ...assets] = await Promise.all( 513*6b7802baSBartosz Kaszubowski * migratedFiles.map<Promise<MediaLibrary.Asset>>( 514*6b7802baSBartosz Kaszubowski * async fileName => await MediaLibrary.createAssetAsync(outputDir + '/' + fileName) 515*6b7802baSBartosz Kaszubowski * ) 516*6b7802baSBartosz Kaszubowski * ); 517*6b7802baSBartosz Kaszubowski * 518*6b7802baSBartosz Kaszubowski * // Album was empty 519*6b7802baSBartosz Kaszubowski * if (!newAlbumCreator) { 520*6b7802baSBartosz Kaszubowski * return; 521*6b7802baSBartosz Kaszubowski * } 522*6b7802baSBartosz Kaszubowski * 523*6b7802baSBartosz Kaszubowski * // Creates a new album in the scoped directory 524*6b7802baSBartosz Kaszubowski * const newAlbum = await MediaLibrary.createAlbumAsync(albumName, newAlbumCreator, false); 525*6b7802baSBartosz Kaszubowski * if (assets.length) { 526*6b7802baSBartosz Kaszubowski * await MediaLibrary.addAssetsToAlbumAsync(assets, newAlbum, false); 527*6b7802baSBartosz Kaszubowski * } 528*6b7802baSBartosz Kaszubowski * } 529*6b7802baSBartosz Kaszubowski * ``` 530*6b7802baSBartosz Kaszubowski * @platform Android 531400de723SŁukasz Kosmaty */ 532400de723SŁukasz Kosmatyexport var StorageAccessFramework; 533400de723SŁukasz Kosmaty(function (StorageAccessFramework) { 534*6b7802baSBartosz Kaszubowski /** 535*6b7802baSBartosz Kaszubowski * Gets a [SAF URI](#saf-uri) pointing to a folder in the Android root directory. You can use this function to get URI for 536*6b7802baSBartosz Kaszubowski * `StorageAccessFramework.requestDirectoryPermissionsAsync()` when you trying to migrate an album. In that case, the name of the album is the folder name. 537*6b7802baSBartosz Kaszubowski * @param folderName The name of the folder which is located in the Android root directory. 538*6b7802baSBartosz Kaszubowski * @return Returns a [SAF URI](#saf-uri) to a folder. 539*6b7802baSBartosz Kaszubowski */ 540400de723SŁukasz Kosmaty function getUriForDirectoryInRoot(folderName) { 541400de723SŁukasz Kosmaty return `content://com.android.externalstorage.documents/tree/primary:${folderName}/document/primary:${folderName}`; 542400de723SŁukasz Kosmaty } 543400de723SŁukasz Kosmaty StorageAccessFramework.getUriForDirectoryInRoot = getUriForDirectoryInRoot; 544*6b7802baSBartosz Kaszubowski /** 545*6b7802baSBartosz Kaszubowski * Allows users to select a specific directory, granting your app access to all of the files and sub-directories within that directory. 546*6b7802baSBartosz Kaszubowski * @param initialFileUrl The [SAF URI](#saf-uri) of the directory that the file picker should display when it first loads. 547*6b7802baSBartosz Kaszubowski * If URI is incorrect or points to a non-existing folder, it's ignored. 548*6b7802baSBartosz Kaszubowski * @platform android 11+ 549*6b7802baSBartosz Kaszubowski * @return Returns a Promise that resolves to `FileSystemRequestDirectoryPermissionsResult` object. 550*6b7802baSBartosz Kaszubowski */ 551400de723SŁukasz Kosmaty async function requestDirectoryPermissionsAsync(initialFileUrl = null) { 552400de723SŁukasz Kosmaty if (!ExponentFileSystem.requestDirectoryPermissionsAsync) { 553400de723SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.requestDirectoryPermissionsAsync'); 554400de723SŁukasz Kosmaty } 555400de723SŁukasz Kosmaty return await ExponentFileSystem.requestDirectoryPermissionsAsync(initialFileUrl); 556400de723SŁukasz Kosmaty } 557400de723SŁukasz Kosmaty StorageAccessFramework.requestDirectoryPermissionsAsync = requestDirectoryPermissionsAsync; 558*6b7802baSBartosz Kaszubowski /** 559*6b7802baSBartosz Kaszubowski * Enumerate the contents of a directory. 560*6b7802baSBartosz Kaszubowski * @param dirUri [SAF](#saf-uri) URI to the directory. 561*6b7802baSBartosz Kaszubowski * @return A Promise that resolves to an array of strings, each containing the full [SAF URI](#saf-uri) of a file or directory contained in the directory at `fileUri`. 562*6b7802baSBartosz Kaszubowski */ 563400de723SŁukasz Kosmaty async function readDirectoryAsync(dirUri) { 564400de723SŁukasz Kosmaty if (!ExponentFileSystem.readSAFDirectoryAsync) { 565400de723SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.readDirectoryAsync'); 566400de723SŁukasz Kosmaty } 567400de723SŁukasz Kosmaty return await ExponentFileSystem.readSAFDirectoryAsync(dirUri, {}); 568400de723SŁukasz Kosmaty } 569400de723SŁukasz Kosmaty StorageAccessFramework.readDirectoryAsync = readDirectoryAsync; 570*6b7802baSBartosz Kaszubowski /** 571*6b7802baSBartosz Kaszubowski * Creates a new empty directory. 572*6b7802baSBartosz Kaszubowski * @param parentUri The [SAF](#saf-uri) URI to the parent directory. 573*6b7802baSBartosz Kaszubowski * @param dirName The name of new directory. 574*6b7802baSBartosz Kaszubowski * @return A Promise that resolves to a [SAF URI](#saf-uri) to the created directory. 575*6b7802baSBartosz Kaszubowski */ 576400de723SŁukasz Kosmaty async function makeDirectoryAsync(parentUri, dirName) { 577400de723SŁukasz Kosmaty if (!ExponentFileSystem.makeSAFDirectoryAsync) { 578400de723SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.makeDirectoryAsync'); 579400de723SŁukasz Kosmaty } 580400de723SŁukasz Kosmaty return await ExponentFileSystem.makeSAFDirectoryAsync(parentUri, dirName); 581400de723SŁukasz Kosmaty } 582400de723SŁukasz Kosmaty StorageAccessFramework.makeDirectoryAsync = makeDirectoryAsync; 583*6b7802baSBartosz Kaszubowski /** 584*6b7802baSBartosz Kaszubowski * Creates a new empty file. 585*6b7802baSBartosz Kaszubowski * @param parentUri The [SAF](#saf-uri) URI to the parent directory. 586*6b7802baSBartosz Kaszubowski * @param fileName The name of new file **without the extension**. 587*6b7802baSBartosz Kaszubowski * @param mimeType The MIME type of new file. 588*6b7802baSBartosz Kaszubowski * @return A Promise that resolves to a [SAF URI](#saf-uri) to the created file. 589*6b7802baSBartosz Kaszubowski */ 590400de723SŁukasz Kosmaty async function createFileAsync(parentUri, fileName, mimeType) { 591400de723SŁukasz Kosmaty if (!ExponentFileSystem.createSAFFileAsync) { 592400de723SŁukasz Kosmaty throw new UnavailabilityError('expo-file-system', 'StorageAccessFramework.createFileAsync'); 593400de723SŁukasz Kosmaty } 594400de723SŁukasz Kosmaty return await ExponentFileSystem.createSAFFileAsync(parentUri, fileName, mimeType); 595400de723SŁukasz Kosmaty } 596400de723SŁukasz Kosmaty StorageAccessFramework.createFileAsync = createFileAsync; 597*6b7802baSBartosz Kaszubowski /** 598*6b7802baSBartosz Kaszubowski * Alias for [`writeAsStringAsync`](#filesystemwriteasstringasyncfileuri-contents-options) method. 599*6b7802baSBartosz Kaszubowski */ 600400de723SŁukasz Kosmaty StorageAccessFramework.writeAsStringAsync = baseWriteAsStringAsync; 601*6b7802baSBartosz Kaszubowski /** 602*6b7802baSBartosz Kaszubowski * Alias for [`readAsStringAsync`](#filesystemreadasstringasyncfileuri-options) method. 603*6b7802baSBartosz Kaszubowski */ 604400de723SŁukasz Kosmaty StorageAccessFramework.readAsStringAsync = baseReadAsStringAsync; 605*6b7802baSBartosz Kaszubowski /** 606*6b7802baSBartosz Kaszubowski * Alias for [`deleteAsync`](#filesystemdeleteasyncfileuri-options) method. 607*6b7802baSBartosz Kaszubowski */ 608400de723SŁukasz Kosmaty StorageAccessFramework.deleteAsync = baseDeleteAsync; 609*6b7802baSBartosz Kaszubowski /** 610*6b7802baSBartosz Kaszubowski * Alias for [`moveAsync`](#filesystemmoveasyncoptions) method. 611*6b7802baSBartosz Kaszubowski */ 612400de723SŁukasz Kosmaty StorageAccessFramework.moveAsync = baseMoveAsync; 613*6b7802baSBartosz Kaszubowski /** 614*6b7802baSBartosz Kaszubowski * Alias fro [`copyAsync`](#filesystemcopyasyncoptions) method. 615*6b7802baSBartosz Kaszubowski */ 616400de723SŁukasz Kosmaty StorageAccessFramework.copyAsync = baseCopyAsync; 617400de723SŁukasz Kosmaty})(StorageAccessFramework || (StorageAccessFramework = {})); 6182307aaceSEvan Bacon//# sourceMappingURL=FileSystem.js.map