simple_downloader 0.0.3+1 copy "simple_downloader: ^0.0.3+1" to clipboard
simple_downloader: ^0.0.3+1 copied to clipboard

flutter plugin for handling download file using http with pause, resume, cancel, retry, restart & open file downloader features.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:path_provider/path_provider.dart' as path;
import 'package:simple_downloader/simple_downloader.dart';

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late SimpleDownloader _downloader;

  double _progress = 0.0;
  int _offset = 0;
  int _total = 0;
  DownloadStatus _status = DownloadStatus.undefined;
  DownloaderTask _task = const DownloaderTask(
    url:
        "https://images.unsplash.com/photo-1615220368123-9bb8faf4221b?ixlib=rb-1.2.1&dl=vadim-kaipov-f6jkAE1ZWuY-unsplash.jpg&q=80&fm=jpg&crop=entropy&cs=tinysrgb",
    fileName: "images_downloaded.jpg",
    bufferSize:
        1024, // if bufferSize value not set, default value is 64 ( 64 Kb )
  );

  @override
  void initState() {
    super.initState();
    init();
  }

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(20.0),
          child: Container(
            height: 150,
            width: double.maxFinite,
            decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(20),
                boxShadow: const [
                  BoxShadow(
                    color: Colors.black12,
                    offset: Offset(0, 3),
                    spreadRadius: 3,
                    blurRadius: 3,
                  )
                ]),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                ListTile(
                  visualDensity:
                      const VisualDensity(horizontal: -4, vertical: 0),
                  title: Text(_task.fileName ?? ""),
                  subtitle: labelStatus,
                  trailing: trailingIcon,
                ),
                const SizedBox(height: 25.0),
                Padding(
                  padding: const EdgeInsets.only(left: 15.0, right: 15.0),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Text("${_offset ~/ 1024} Kb / ${_total ~/ 1024} Kb",
                              textAlign: TextAlign.right),
                          Text("${_progress.floor()} %",
                              textAlign: TextAlign.right),
                        ],
                      ),
                      const SizedBox(height: 5),
                      LinearProgressIndicator(
                        value: _progress / 100,
                      )
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Future<void> init() async {
    final pathFile = (await path.getExternalStorageDirectory())!.path;
    if (!mounted) return;

    _task = _task.copyWith(
      downloadPath: pathFile,
    );

    _downloader = SimpleDownloader.init(task: _task);

    _downloader.callback.addListener(() {
      setState(() {
        _progress = _downloader.callback.progress;
        _status = _downloader.callback.status;
        _total = _downloader.callback.total;
        _offset = _downloader.callback.offset;
      });
    });
  }

  Widget get labelStatus {
    switch (_status) {
      case DownloadStatus.undefined:
        return const Text("Waiting..");
      case DownloadStatus.completed:
        return const Text("Download Completed");
      case DownloadStatus.failed:
        return const Text("Download Failed");
      case DownloadStatus.paused:
        return const Text("Download Paused");
      case DownloadStatus.deleted:
        return const Text("File Deleted");
      case DownloadStatus.canceled:
        return const Text("Download Canceled");
      default:
        return const Text("Downloading");
    }
  }

  Widget? get trailingIcon {
    if (_status == DownloadStatus.undefined ||
        _status == DownloadStatus.deleted) {
      return IconButton(
        splashRadius: 20,
        onPressed: () => _downloader.download(),
        constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
        icon: const Icon(
          Icons.play_arrow,
        ),
      );
    }
    if (_status == DownloadStatus.running ||
        _status == DownloadStatus.resume ||
        _status == DownloadStatus.retry) {
      return Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          IconButton(
            splashRadius: 20,
            onPressed: () => _downloader.pause(),
            constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
            icon: const Icon(
              Icons.pause,
              color: Colors.green,
            ),
          ),
          IconButton(
            splashRadius: 20,
            onPressed: () => _downloader.cancel(),
            constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
            icon: const Icon(
              Icons.close,
              color: Colors.red,
            ),
          ),
        ],
      );
    }
    if (_status == DownloadStatus.paused) {
      return Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          IconButton(
            splashRadius: 20,
            onPressed: () => _downloader.resume(),
            constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
            icon: const Icon(
              Icons.play_arrow,
              color: Colors.blue,
            ),
          ),
          IconButton(
            splashRadius: 20,
            onPressed: () => _downloader.cancel(),
            constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
            icon: const Icon(
              Icons.close,
              color: Colors.red,
            ),
          ),
        ],
      );
    }

    if (_status == DownloadStatus.completed) {
      return Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          IconButton(
            tooltip: "Open file",
            splashRadius: 20,
            onPressed: () async {
              _downloader.open().then(
                (isSuccess) {
                  if (!isSuccess!) {
                    showMessage(context, "Failed to open downloaded file.");
                  }
                },
              );
            },
            constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
            icon: const Icon(
              Icons.file_open,
              color: Colors.green,
            ),
          ),
          IconButton(
            tooltip: "Delete file",
            splashRadius: 20,
            onPressed: () => _downloader.delete(),
            constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
            icon: const Icon(
              Icons.delete,
              color: Colors.red,
            ),
          ),
        ],
      );
    }

    if (_status == DownloadStatus.failed ||
        _status == DownloadStatus.canceled) {
      return Row(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            IconButton(
              splashRadius: 20,
              onPressed: () => _downloader.retry(),
              constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
              icon: const Icon(
                Icons.refresh,
                color: Colors.green,
              ),
            ),
            IconButton(
              splashRadius: 20,
              onPressed: () => _downloader.restart(),
              constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
              icon: const Icon(
                Icons.restart_alt,
                color: Colors.red,
              ),
            ),
          ]);
    }

    return null;
  }

  Future<void> showMessage(
    BuildContext context,
    String message,
  ) async {
    final size = MediaQuery.of(context).size;
    return showModalBottomSheet(
        elevation: 2,
        isDismissible: false,
        enableDrag: false,
        shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
              topLeft: Radius.circular(30), topRight: Radius.circular(30)),
        ),
        context: context,
        builder: (builder) {
          return SizedBox(
            height: 250,
            child: Stack(children: [
              Positioned(
                top: 10,
                right: 10,
                child: IconButton(
                  splashRadius: 25,
                  onPressed: () => Navigator.pop(context),
                  icon: const Icon(
                    Icons.close,
                    size: 25,
                  ),
                ),
              ),
              Center(
                child: Container(
                  constraints: BoxConstraints(
                    maxWidth: 0.8 * size.width,
                  ),
                  child: Text(
                    message,
                    textAlign: TextAlign.center,
                    style: const TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ),
              ),
              Positioned(
                bottom: 20,
                right: 20,
                left: 20,
                child: ElevatedButton(
                  child: const Text(
                    "OK",
                    style: TextStyle(
                        color: Colors.white, fontWeight: FontWeight.w600),
                  ),
                  onPressed: () => Navigator.pop(context),
                ),
              ),
            ]),
          );
        });
  }
}
11
likes
150
points
4
downloads

Publisher

unverified uploader

Weekly Downloads

flutter plugin for handling download file using http with pause, resume, cancel, retry, restart & open file downloader features.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

async, flutter, http, mime, path, plugin_platform_interface

More

Packages that depend on simple_downloader

Packages that implement simple_downloader