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