로메오의 블로그

[React Native] 리소스 파일 다운로드하기 (zip 압축해제) 본문

App & OS/Hybrid

[React Native] 리소스 파일 다운로드하기 (zip 압축해제)

romeoh 2019. 7. 13. 04:53
반응형

Firebase 목록

 

[REACT NATIVE] 디바이스에 LOCAL SERVER 구동하기

앞서 디바이스에서 local server를 구동하는 방법을 알아봤습니다.

firebase hosting에서 리소스를 zip으로 압축해서 올려두고

React Native에서 zip을 다운로드해서 압축 해제하고 local server로 표시하는 고오급 기능을 구현해보겠습니다.

 

Firebase hosting에 zip파일 업로드

index.html

<html>
    <head>
        <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
        <title>hello world</title>
        <link rel="stylesheet" href="style.css">
    </head>

    <body>
        <h1 class="title"></h1>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script src="script.js"></script>
    </body>
</html>

script.js

$(window).on('load', function() {
    $('h1').text('hello World!!')
})

style.css

body {margin-top: 100px}
.title {color: #f0f}

www폴더를 만들고 index.html, script.js, style.css 파일을 만들어서 resource.zip파일로 압축합니다.

 

firebase hosting 프로젝트인 firstProject/public 폴더에 넣어둡니다.

firebase hosting 프로젝트에 대한 아래 포스트를 참조하세요.

[FIREBASE] 호스팅 생성하고 배포하기

 

firebase 배포하기

resource.zip 파일 이외의 파일들은 삭제해도 상관없습니다.

$ cd /my/project/path
$ cd firstProject
$ firebase deploy

 

React Native 모듈 추가 설치

$ npm install react-native-fetch-blob
$ react-native link react-native-fetch-blob
$ npm install react-native-zip-archive
$ react-native link react-native-zip-archive

react-native-fetch-blob: 바이너리 파일을 다운로드 한다.

react-native-zip-archive: zip 파일을 압축/해제 한다.

 

최종 package.json 파일입니다.

{
  "name": "secondProject",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.8.3",
    "react-native": "0.59.8",
    "react-native-fetch-blob": "^0.10.8",
    "react-native-fs": "^2.13.3",
    "react-native-static-server": "^0.4.2",
    "react-native-webview": "^5.12.1",
    "react-native-zip-archive": "^4.1.1"
  },
  "devDependencies": {
    "@babel/core": "7.5.4",
    "@babel/runtime": "7.5.4",
    "babel-jest": "24.8.0",
    "jest": "24.8.0",
    "metro-react-native-babel-preset": "0.55.0",
    "react-test-renderer": "16.8.3"
  },
  "jest": {
    "preset": "react-native"
  }
}

App.js 코드 수정

import React, { Component } from 'react';
import { Platform, StyleSheet, View } from 'react-native';
import { WebView } from 'react-native-webview'
import StaticServer from 'react-native-static-server';
import RNFS from 'react-native-fs';
import RNFetchBlob from 'react-native-fetch-blob';
import { unzip } from 'react-native-zip-archive';

const port = 9898;

// local server의 home 디렉토리를 지정합니다.
const documentPath = RNFS.DocumentDirectoryPath;

// local server에 port와 document path를 지정합니다.
const server = new StaticServer(port, documentPath);

// resource.zip 파일 경로
const resourceUrl = 'https://firstproject-a04bf.firebaseapp.com/resource.zip'

export default class App extends Component {

    constructor(props) {
        super(props);
        this.state = {
            indexPage: Platform.OS === 'ios'
                ? require('./www/loading.html')
                : { uri: 'file:///android_asset/loading.html' },
            domain: ''
        };
    }

    componentDidMount() {
        // 서버를 구동합니다.
        this.startStaticServer()
    }

    componentWillUnmount() {
        // 서버 정지
        server.stop();
    }

    /**
     * 서버를 구동한다.
     */
    startStaticServer = () => {
        server.start().then(url => {
            console.log('server start at: ' + documentPath + ' [' + url + ']');

            // local server IP 주소를 state에 저장한다.
            this.setState({
                domain: url
            })

            // 리소스를 다운로드 한다.
            this.downloadResource()
        })
    }

    /**
     * 리소스르 다운로드한다.
     */
    downloadResource = () => {

        // 디바이스에 저장할 경로 설정
        const dirs = RNFetchBlob.fs.dirs.DocumentDir
        const homePath = dirs + '/resource.zip'

        // resource.zip 파일 다운로드
        RNFetchBlob
            .config({
                path: homePath
            })
            .fetch('GET', resourceUrl)
            .progress((received, total) => {
                // console.log('progress', received, total)
                const percentage = Math.floor(received / total * 10000) / 100 + '%'
                console.log(percentage)
            })
            .then(resourceFile => {
                console.log('resource.zip 파일 다운로드 성공')

                // zip 파일 압축 해제
                this.unzipResource(resourceFile);
            })
            .catch((errorMessage, statusCode) => {
                console.log(errorMessage);
            })
    }

    /**
     * zip 파일을 압축해제한다.
     */
    unzipResource = resourceFile => {
        const resourcePath = resourceFile.path()
        unzip(resourcePath, documentPath)
            .then(path => {
                console.log(`unzip 성공: ${path}`)
                this.setState({
                    indexPage: {
                        uri: this.state.domain + '/index.html?ver=2'
                    }
                })
            })
    }

    render() {
        return (
            <View style={styles.container}>
                <WebView
                    style={styles.webview}
                    source={this.state.indexPage}
                    originWhitelist={['*']}
                    ref={webview => this.appWebview = webview}
                    javaScriptEnabled={true}
                    useWebKit={true}
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    webview: {

    }
});

react native 코드를 수정합니다. (주석 참조)

 

iOS Build

$ react-native run-ios

앱을 구동하고 document 폴더에 가보면 resource.zip 파일을 다운로드 해서 압축 해제된 것을 볼 수 있습니다.

조형미가 물씬 풍기는 Hello world를 확인 할 수 있습니다. (나 디자이너 출신인데..-_-)

 

Android Build

$ react-native run-android

Device File Explorer에 resource.zip 파일이 다운로드되어 압축해제된 것을 확인 할 수 있습니다.

역시 아름다운 Hello World를 볼 수 있습니다.

 

Firebase 목록

반응형
Comments