1import AsyncStorage from '@react-native-community/async-storage'; 2import { Asset } from 'expo-asset'; 3import * as FileSystem from 'expo-file-system'; 4import * as Progress from 'expo-progress'; 5import React from 'react'; 6import { Alert, ScrollView, StyleSheet } from 'react-native'; 7 8import ListButton from '../components/ListButton'; 9 10interface State { 11 downloadProgress: number; 12} 13 14export default class FileSystemScreen extends React.Component<object, State> { 15 static navigationOptions = { 16 title: 'FileSystem', 17 }; 18 19 readonly state: State = { 20 downloadProgress: 0, 21 }; 22 23 download?: FileSystem.DownloadResumable; 24 25 _download = async () => { 26 const url = 'http://ipv4.download.thinkbroadband.com/256KB.zip'; 27 await FileSystem.downloadAsync(url, FileSystem.documentDirectory + '256KB.zip'); 28 alert('Download complete!'); 29 }; 30 31 _startDownloading = async () => { 32 const url = 'http://ipv4.download.thinkbroadband.com/5MB.zip'; 33 const fileUri = FileSystem.documentDirectory + '5MB.zip'; 34 const callback: FileSystem.DownloadProgressCallback = downloadProgress => { 35 const progress = 36 downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite; 37 this.setState({ 38 downloadProgress: progress, 39 }); 40 }; 41 const options = { md5: true }; 42 this.download = FileSystem.createDownloadResumable(url, fileUri, options, callback); 43 44 try { 45 const result = await this.download.downloadAsync(); 46 if (result) { 47 this._downloadComplete(); 48 } 49 } catch (e) { 50 console.log(e); 51 } 52 }; 53 54 _pause = async () => { 55 if (!this.download) { 56 alert('Initiate a download first!'); 57 return; 58 } 59 try { 60 const downloadSnapshot = await this.download.pauseAsync(); 61 await AsyncStorage.setItem('pausedDownload', JSON.stringify(downloadSnapshot)); 62 alert('Download paused...'); 63 } catch (e) { 64 console.log(e); 65 } 66 }; 67 68 _resume = async () => { 69 try { 70 if (this.download) { 71 const result = await this.download.resumeAsync(); 72 if (result) { 73 this._downloadComplete(); 74 } 75 } else { 76 this._fetchDownload(); 77 } 78 } catch (e) { 79 console.log(e); 80 } 81 }; 82 83 _downloadComplete = () => { 84 if (this.state.downloadProgress !== 1) { 85 this.setState({ 86 downloadProgress: 1, 87 }); 88 } 89 alert('Download complete!'); 90 }; 91 92 _fetchDownload = async () => { 93 try { 94 const downloadJson = await AsyncStorage.getItem('pausedDownload'); 95 if (downloadJson !== null) { 96 const downloadFromStore = JSON.parse(downloadJson); 97 const callback: FileSystem.DownloadProgressCallback = downloadProgress => { 98 const progress = 99 downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite; 100 this.setState({ 101 downloadProgress: progress, 102 }); 103 }; 104 this.download = new FileSystem.DownloadResumable( 105 downloadFromStore.url, 106 downloadFromStore.fileUri, 107 downloadFromStore.options, 108 callback, 109 downloadFromStore.resumeData 110 ); 111 await this.download.resumeAsync(); 112 if (this.state.downloadProgress === 1) { 113 alert('Download complete!'); 114 } 115 } else { 116 alert('Initiate a download first!'); 117 return; 118 } 119 } catch (e) { 120 console.log(e); 121 } 122 }; 123 124 _getInfo = async () => { 125 if (!this.download) { 126 alert('Initiate a download first!'); 127 return; 128 } 129 try { 130 const info = await FileSystem.getInfoAsync(this.download._fileUri); 131 Alert.alert('File Info:', JSON.stringify(info), [{ text: 'OK', onPress: () => {} }]); 132 } catch (e) { 133 console.log(e); 134 } 135 }; 136 137 _readAsset = async () => { 138 const asset = Asset.fromModule(require('../../assets/index.html')); 139 await asset.downloadAsync(); 140 try { 141 const result = await FileSystem.readAsStringAsync(asset.localUri!); 142 Alert.alert('Result', result); 143 } catch (e) { 144 Alert.alert('Error', e.message); 145 } 146 }; 147 148 _getInfoAsset = async () => { 149 const asset = Asset.fromModule(require('../../assets/index.html')); 150 await asset.downloadAsync(); 151 try { 152 const result = await FileSystem.getInfoAsync(asset.localUri!); 153 Alert.alert('Result', JSON.stringify(result, null, 2)); 154 } catch (e) { 155 Alert.alert('Error', e.message); 156 } 157 }; 158 159 _copyAndReadAsset = async () => { 160 const asset = Asset.fromModule(require('../../assets/index.html')); 161 await asset.downloadAsync(); 162 const tmpFile = FileSystem.cacheDirectory + 'test.html'; 163 try { 164 await FileSystem.copyAsync({ from: asset.localUri!, to: tmpFile }); 165 const result = await FileSystem.readAsStringAsync(tmpFile); 166 Alert.alert('Result', result); 167 } catch (e) { 168 Alert.alert('Error', e.message); 169 } 170 }; 171 172 _alertFreeSpace = async () => { 173 const freeBytes = await FileSystem.getFreeDiskStorageAsync(); 174 alert(`${Math.round(freeBytes / 1024 / 1024)} MB available`); 175 }; 176 177 render() { 178 return ( 179 <ScrollView style={{ padding: 10 }}> 180 <ListButton onPress={this._download} title="Download file (512KB)" /> 181 <ListButton onPress={this._startDownloading} title="Start Downloading file (5MB)" /> 182 <ListButton onPress={this._pause} title="Pause Download" /> 183 <ListButton onPress={this._resume} title="Resume Download" /> 184 <ListButton onPress={this._getInfo} title="Get Info" /> 185 <Progress.Bar style={styles.progress} isAnimated progress={this.state.downloadProgress} /> 186 <ListButton onPress={this._readAsset} title="Read Asset" /> 187 <ListButton onPress={this._getInfoAsset} title="Get Info Asset" /> 188 <ListButton onPress={this._copyAndReadAsset} title="Copy and Read Asset" /> 189 <ListButton onPress={this._alertFreeSpace} title="Alert free space" /> 190 </ScrollView> 191 ); 192 } 193} 194 195const styles = StyleSheet.create({ 196 progress: { 197 marginHorizontal: 10, 198 marginVertical: 32, 199 }, 200}); 201