7

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

Mr P
  • 129
  • 1
  • 2
  • 10
  • Have you tried this solution? https://stackoverflow.com/questions/57995621/how-to-download-a-file-and-store-it-in-downloads-folder-using-flutter – Bilaal Abdel Hassan May 06 '20 at 21:47

3 Answers3

13

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),
      ),
    );
  }
}
chunhunghan
  • 51,087
  • 5
  • 102
  • 120
  • Tried this on my project though... Got an error which i have been trying to fix: * What went wrong: Execution failed for task ':app:preDebugBuild'. > Android dependency 'androidx.core:core' has different version for the compile (1.1.0-rc03) and runtime (1.1.0) classpath. You should manually set the same version via DependencyResolution – Mr P May 08 '20 at 12:37
  • I have fixed the additional issue that came up and then this worked perfectly. Thanks alot @chunhunghan. The permission handler and this line of code String path = await ExtStorage.getExternalStoragePublicDirectory( ExtStorage.DIRECTORY_DOWNLOADS); is a must for this to work... Even with other methods of downloading file to phone. Thanks once again – Mr P May 08 '20 at 23:31
  • Glad to help. please mark this as answer if it helps you. thanks. – chunhunghan May 11 '20 at 00:41
  • 2
    I found out that this way large files can't be downloaded, using `dio.download()` instead solves the issue. – Amani Saaduddin Nov 26 '20 at 17:17
  • For Android 10, we can't use the common download directory - so use ```(await getApplicationDocumentsDirectory()).path``` instead – quilkin Feb 01 '21 at 23:31
  • This works fine on Android. But doesn't help with iOS – ABM Jun 14 '21 at 13:52
  • this was not working. that package was not a null safety. any alternatives ? – Phanindra Sep 09 '21 at 14:50
  • `https://pub.dev/packages/ext_storage` package is not NULL SAFETY so not worked for me. Thanks. – Kamlesh Sep 10 '21 at 09:11
0

I haven't tested it, but if you want to save your downloaded files to the download directory, there is a package for that : downloads_path_provider

If you encounter issues, you can use the path_provider package instead. It gives you access to several directories of devices.

F Perroch
  • 1,988
  • 2
  • 11
  • 23
0

You can use "flutter_file_dialog" to handle the issue. After succesfully saving file into app you can provide the path of file to this package and save it in another folder of phone. You can use the function below; ** fromDest ** is the path of the saved file.

_saveFileToDest(String fromDest) async {
   final params =
            SaveFileDialogParams(sourceFilePath: fromDest);
        final filePath = await FlutterFileDialog.saveFile(params: params);
        if (kDebugMode) {
          print(filePath);
        }
  }
Yusuf GÜR
  • 31
  • 5