파일다운로드시 진행상태 표시 예제

 

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  dio: ^4.0.6
  path_provider: ^2.0.11

 

main.dart

import "package:flutter/material.dart";
import "package:largefile_download/LargeFileMain.dart";

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Large file download App",
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const LargeFileMain(title: "This is large file download App!"),
    );
  }
}

 

LargeFileMain.dart

import "package:flutter/material.dart";
import "package:dio/dio.dart";
import "package:path_provider/path_provider.dart";
import "dart:io";

class LargeFileMain extends StatefulWidget {
  const LargeFileMain({super.key, required this.title});

  final String title;

  @override
  State<StatefulWidget> createState() {
    return _LargeFileMain();
  }
}

class _LargeFileMain extends State<LargeFileMain> {
  TextEditingController? _textEditingController;
  bool downloading = false;
  var progressString = "";
  String file = "";

  @override
  void initState() {
    super.initState();
    _textEditingController = TextEditingController(text: "https://images.pexels.com/photos/240040/pexels-photo-240040.jpeg?auto=compress");
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextField(
          controller: _textEditingController,
          keyboardType: TextInputType.url,
          style: const TextStyle(color: Colors.white),
          decoration: const InputDecoration(hintText: "url을 입력하세요."),
        )
      ),
      body: Center(
        child: downloading
            ? SizedBox(
              height: 120.0,
              width: 200.0,
              child: Card(
                color: Colors.black,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    const CircularProgressIndicator(),
                    const SizedBox(
                      height: 20.0,
                    ),
                    Text(
                      "Downloading File: $progressString",
                      style: const TextStyle(
                        color: Colors.white,
                      ),
                    ),
                  ],
                ),
              ),
            )
            : FutureBuilder(
              builder: (context, snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                    print("none");
                    return const Text("데이터 없음");
                    break;
                  case ConnectionState.waiting:
                    print("waiting");
                    return const CircularProgressIndicator();
                    break;
                  case ConnectionState.active:
                    print("active");
                    return const CircularProgressIndicator();
                    break;
                  case ConnectionState.done:
                    print("done");
                    if (snapshot.hasData) {
                      return snapshot.data as Widget;
                    }
                    break;
                }
                print("end process");
                return const Text("There is no data.");
            },
            future: _downloadWidget(file),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _download();
        },
        child: const Icon(Icons.file_download),
      ),
    );
  }

  Future<void> _download() async {
    Dio dio = Dio();

    try {
      Directory dir = await getApplicationDocumentsDirectory();
      await dio.download(_textEditingController!.value.text, "${dir.path}/myimage.jpg",
        onReceiveProgress: (rec, total) {
          //print("Rec: $rec, Total: $total");
          file = "${dir.path}/myimage.jpg";
          //print(dir.path);
          setState(() {
            downloading = true;
            progressString = "${((rec / total) * 100).toStringAsFixed(0)}%";
          });
        }
      );
    } catch (e) {
      print(e);
    }

    setState(() {
      downloading = false;
      progressString = "Completed!";
    });

    print("Download completed!");
  }

  Future<Widget> _downloadWidget(String filePath) async {
    File file = File(filePath);
    bool exist = await file.exists();
    FileImage(file).evict();

    if (exist) {
      return Center(
        child: Column(
          children: <Widget>[
            Image.file(File(filePath)),
          ],
        ),
      );
    }
    else {
      return const Text("There is no data");
    }
  }
}