Search code examples
flutterdartpathproviderdio

Flutter download file to phone download directory


I have searched for similar questions and answers to this question but haven't found any specific answer till now. I am trying to save downloaded files to my internal phone storage. Preferably the download folder... Am using d i o and path provider. Have tried using "get External Storage Directory". But even after the download I can't locate the file anywhere in my device. Please how do I specify the download path to something like /storage/emulated/0/Download


Solution

  • You can copy paste run full code below
    This example code download a pdf file with Dio and save to Downloads directory
    Step 1: downloads_path_provider has archived by the owner, you can use package https://pub.dev/packages/ext_storage
    code snippet

    String path = await ExtStorage.getExternalStoragePublicDirectory(
        ExtStorage.DIRECTORY_DOWNLOADS);
    print(path);
    

    Step 2: Add permission in AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    Step 3: pubspec.yaml , notice permission_handler is 4.4.0

    dependencies:
      flutter:
        sdk: flutter
      dio: any
      permission_handler: 4.4.0
      ext_storage: any
    

    Step 4: Dio for download file

    Future download2(Dio dio, String url, String savePath) async {
        try {
          Response response = await dio.get(
            url,
            onReceiveProgress: showDownloadProgress,
            //Received data with List<int>
            options: Options(
                responseType: ResponseType.bytes,
                followRedirects: false,
                validateStatus: (status) {
                  return status < 500;
                }),
          );
          print(response.headers);
          File file = File(savePath);
          var raf = file.openSync(mode: FileMode.write);
          // response.data is List<int> type
          raf.writeFromSync(response.data);
          await raf.close();
        } catch (e) {
          print(e);
        }
      }
    

    output

    I/flutter (13605): full path /storage/emulated/0/Download/test.pdf
    I/flutter (13605): 62%
    I/flutter (13605): 100%
    

    enter image description here

    full code

    import 'package:flutter/material.dart';
    import 'package:dio/dio.dart';
    import 'package:ext_storage/ext_storage.dart';
    import 'dart:io';
    import 'package:permission_handler/permission_handler.dart';
    
    final imgUrl =
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
    
    var dio = Dio();
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      void getPermission() async {
        print("getPermission");
        Map<PermissionGroup, PermissionStatus> permissions =
            await PermissionHandler().requestPermissions([PermissionGroup.storage]);
      }
    
      @override
      void initState() {
        getPermission();
        super.initState();
      }
    
      Future download2(Dio dio, String url, String savePath) async {
        try {
          Response response = await dio.get(
            url,
            onReceiveProgress: showDownloadProgress,
            //Received data with List<int>
            options: Options(
                responseType: ResponseType.bytes,
                followRedirects: false,
                validateStatus: (status) {
                  return status < 500;
                }),
          );
          print(response.headers);
          File file = File(savePath);
          var raf = file.openSync(mode: FileMode.write);
          // response.data is List<int> type
          raf.writeFromSync(response.data);
          await raf.close();
        } catch (e) {
          print(e);
        }
      }
    
      void showDownloadProgress(received, total) {
        if (total != -1) {
          print((received / total * 100).toStringAsFixed(0) + "%");
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                RaisedButton.icon(
                    onPressed: () async {
                      String path =
                          await ExtStorage.getExternalStoragePublicDirectory(
                              ExtStorage.DIRECTORY_DOWNLOADS);
                      //String fullPath = tempDir.path + "/boo2.pdf'";
                      String fullPath = "$path/test.pdf";
                      print('full path ${fullPath}');
    
                      download2(dio, imgUrl, fullPath);
                    },
                    icon: Icon(
                      Icons.file_download,
                      color: Colors.white,
                    ),
                    color: Colors.green,
                    textColor: Colors.white,
                    label: Text('Dowload')),
                Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.display1,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }