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