본문 바로가기

그 땐 App했지/그 땐 Flutter했지

[TAVE/Study]Do it! Flutter 7장 네트워크를 이용해 통신하기②

728x90

211004 월

본문3 예!

내려받기 진행 상황 표시하기


📌 dio: 파일을 내려받는 데 도움을 준다.
📌 path_provider: 패키지와 내부 저장소를 이용한다.

dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 dio: ^4.0.0 path_provider: ^2.0.2

👉🏻 pubspec에 추가

import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; class LargeFileMain extends StatefulWidget { @override State<StatefulWidget> createState() => _LargeFileMain(); } class _LargeFileMain extends State<LargeFileMain> { //내려받을 이미지 주소 final imgUrl = 'https://images.pexels.com/photos/240040/pexels-photo-240040.jpeg' '?auto=compress'; bool downloading = false; //지금 내려받는 중인지 확인하는 변수 var progressString = ""; //현재 얼마나 내려받았는지 표시하는 변수 String file = ""; //내려받는 파일 @override Widget build(BuildContext context) { return null; } }

👉🏻 io 패키지: 파일 입출력을 돕는 패키지

 Future<void> downloadFile() async { Dio dio = Dio(); try { var dir = await getApplicationDocumentsDirectory(); await dio.download(imgUrl, '${dir.path}/myimage.jpg', onReceiveProgress: (rec, total) { print('Rec: $rec , Total: $total'); file = '${dir.path}/myimage.jpg'; setState(() { downloading = true; progressString = ((rec / total) * 100).toStringAsFixed(0) + '%'; }); }); } catch (e) { print(e); } setState(() { downloading = false; progressString = 'Completed'; }); print('Download completed'); } }

👉🏻 파일 내려받는 함수
✍🏻 getApplicationDocumentsDirectory함수: path_provider 패키지가 제공하여 플러터 앱 내부 디렉터리를 가져온다.
✍🏻 dio.download를 이용해 url에 담긴 주소에서 파일을 다운 받는다. 이 파일들은 myimage.jpg라는 이름으로 저장한다.
✍🏻 onReceiveProgress함수: 진행 상황을 표시한다. rec: 지금까지 내려받은 데이터/ total: 파일의 전체 크기
✍🏻 내려받기가 시작되면 downloading = True하고 얼마나 받았는지 계산한다. 완료했으면 false로 고치고 문자열은 completed를 출력한다.

 @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Large File Example'), ), body: Center( child: downloading ? Container( height: 120.0, width: 200.0, child: Card( color: Colors.black, child: Card( color: Colors.black, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ CircularProgressIndicator(), SizedBox( height: 20.0, ), Text( 'Downloading File: $progressString', style: TextStyle( color: Colors.white, ), ) ], ), ), ) : floatingActionButton: FloatingActionButton( onPressed: () { downloadFile(); }, child: Icon(Icons.file_download) ), ); }

👉🏻 파일 다운이 얼마나 진행되었는지 확인하기 위해 위젯을 설정한다.
✍🏻 downloading이 true인 것은 파일을 내려받고 있다는 것이다.
✍🏻 SizedBox 위젯: 고정된 높이과 넓이 안에서 네모난 형태의 위젯을 만들 수 있다.

 : FutureBuilder( builder: (context, snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: print('none'); return Text('데이터 없음'); case ConnectionState.waiting: print('waiting'); return CircularProgressIndicator(); case ConnectionState.active: print('active'); return CircularProgressIndicator(); case ConnectionState.done: print('done'); if (snapshot.hasData) { return snapshot.data as Widget; } } print('end process'); return Text('데이터 없음'); }, Future: downloadWidget(file), )),

👉🏻 FutureBuilder 위젯으로 이미지 내려받기 화면을 만들었다.
✍🏻 FutureBuilder 위젯: 아직 데이터가 없지만 앞으로 데이터를 받아서 처리한 후에 만들겠다는 의미
✍🏻 파일 입출력이나 네트워크 통신 구현은 주로 비동기 방식으로 처리해서 Future를 사용한다.
✍🏻 snapshot은 FutureBuilder.future에서 받아온 데이터를 저장한 dynamic 형태의 변수이다.

 Future<Widget> downloadWidget(String filePath) async { File file = File(filePath); bool exist = await file.exists(); new FileImage(file).evict(); if (exist) { return Center( child: Column( children: <Widget>[Image.file(File(filePath))], ), ); } else { return Text('No Data'); } }


👉🏻 이미지 파일이 있는지 확인해서 있으면 이미지를 화면에 보여주고 없으면 'No Data'를 출력하는 함수이다.
✍🏻 evict() 함수: 캐시를 초기화한다. 캐시란 데이터를 빠르게 처리하기 위해 임시로 저장하는 메모리이다. 플러터는 같은 이름의 파일이 있다면 새로운 것이 아닌 원래 있던 파일을 사용한다. 때문에 미리 초기화해서 이미지를 갱신해서 사용할 수 있도록 해야 한다.

import 'package:flutter/material.dart'; import 'largeFileMain.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: LargeFileMain(), ); } }

👉🏻 main.dart에 LargeFileMain 클래스를 입력한다.

 

URL을 직접 입력해서 내려 받기

 

class _LargeFileMain extends State<LargeFileMain> { bool downloading = false; //지금 내려받는 중인지 확인하는 변수 var progressString = ""; //현재 얼마나 내려받았는지 표시하는 변수 String? file = ""; //내려받는 파일 TextEditingController? _editingController; @override void initState() { super.initState(); _editingController = new TextEditingController( text: 'https://www.motherjones.com/wp-content/uploads/2019/12/Getty121719.jpg?w=1200&h=630&crop=1'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: TextField( controller: _editingController, style: TextStyle(color: Colors.white), keyboardType: TextInputType.text, decoration: InputDecoration(hintText:'url 입력하세요') ), ),

👉🏻 TextEditingController를 생성해 텍스트 필드를 만들어 새로운 URL을 입력하도록 한다.

 Dio dio = Dio(); try { var dir = await getApplicationDocumentsDirectory(); await dio.download(_editingController!.value.text, '${dir.path}/myimage.jpg', onReceiveProgress: (rec, total) { print('Rec: $rec , Total: $total');

👉🏻 텍스트 필드에 입력한 값을 다운로드 받는다.

 

728x90