앱을 사용하다 보면 용량이 큰 파일을 내려받아야 할 때가 있다.
유저는 파일을 내려받을떄 까지 기다려야하는데, 화면에 아무런 정보가 표시되지 않는다면 앱이 멈춘것으로 생각할 수 있다. 파일을 내려받을 때 진행 상황을 표시해줄 필요가 있다.
환경 준비
- dio: 파일을 내려받는 패키지
- path_provider: 내부 저장소 패키지
dependencies:
flutter:
sdk: flutter
dio: ^4.0.0
path_provider: ^2.0.2
화면
코드
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LargeFileMain(),
);
}
}
class LargeFileMain extends StatefulWidget {
@override
State<StatefulWidget> createState() => _LargeFileMainState();
}
class _LargeFileMainState extends State<LargeFileMain> {
bool downloading = false;
var progressString = "";
var file = "";
@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: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(
height: 20.0,
),
Text(
'Downloading File: $progressString',
style: TextStyle(
color: Colors.white,
),
)
],
),
)
) : FutureBuilder(
future: downloadWidget(file),
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('데이터 없음');
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
downloadFile();
},
child: Icon(Icons.file_download),
),
);
}
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: [
Image.file(File(filePath)),
],
),
);
} else {
return Text('No Data');
}
}
Future<void> downloadFile() async {
var dio = Dio();
print('Download started');
try {
var dir = await getTemporaryDirectory();
var response = await dio.download(
'https://images.pexels.com/photos/240040/pexels-photo-240040.jpeg?auth=compress',
'${dir.path}/myimage.jpg',
// './example/flutter.png',
onReceiveProgress: (rec, total) {
print('Rec: $rec, Total: $total');
file = '${dir.path}/myimage.jpg';
setState(() {
downloading = true;
progressString = ((rec / total) * 100).toStringAsFixed(0) + '%';
});
},
options: Options(sendTimeout: 30000, receiveTimeout: 30000),
);
print(response);
} catch (e) {
print(e);
}
setState(() {
downloading = false;
progressString = 'Completed';
});
print('Download completed');
}
}
인터넷 환경에 주의!
참고: 22일차 - 카카오 api 활용하기
Uploaded by Notion2Tistory v1.1.0