Download file from url, save to phones storage

Viewed 95778

I'm working on a project, that requires me to download a file from URL, once a button is tapped, and store it to phone storage (probably downloads folder).

Any ideas on how to do this? The file that is being downloaded is also not always the same and can be anything from an image to a pdf.

5 Answers

Use https://pub.dartlang.org/packages/flutter_downloader. Don't forget to do platform configurations.

Basically, this is how you should use the package. There is a detailed long example in the link.

final taskId = await FlutterDownloader.enqueue(
  url: 'your download link',
  savedDir: 'the path of directory where you want to save downloaded files',
  showNotification: true, // show download progress in status bar (for Android)
  openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);

Edit: Some people said the package on top is to well maintained. Try this one https://pub.dev/packages/flowder

If you want to download and save file from URL without external libraries, you can use this code. It works for me, but I do not check it on big files. Good luck.

Future<String> downloadFile(String url, String fileName, String dir) async {
        HttpClient httpClient = new HttpClient();
        File file;
        String filePath = '';
        String myUrl = '';
    
        try {
          myUrl = url+'/'+fileName;
          var request = await httpClient.getUrl(Uri.parse(myUrl));
          var response = await request.close();
          if(response.statusCode == 200) {
            var bytes = await consolidateHttpClientResponseBytes(response);
            filePath = '$dir/$fileName';
            file = File(filePath);
            await file.writeAsBytes(bytes);
          }
          else
            filePath = 'Error code: '+response.statusCode.toString();
        }
        catch(ex){
          filePath = 'Can not fetch url';
        }
    
        return filePath;
      }

For Android do not forgetto add these lines in the manifest file, otherwise it will not work on real device after build apk:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
static var httpClient = new HttpClient();
Future<File> _downloadFile(String url, String filename) async {
  var request = await httpClient.getUrl(Uri.parse(url));
  var response = await request.close();
  var bytes = await consolidateHttpClientResponseBytes(response);
  String dir = (await getApplicationDocumentsDirectory()).path;
  File file = new File('$dir/$filename');
  await file.writeAsBytes(bytes);
  return file;
}

Use these lib

path_provider: ^2.0.9

open_file: ^3.2.1

for ios add this in Info.plist

<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>

for Android

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

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

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

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

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

and code is

void downloadFileandOpen(BuildContext context, String url, String fileName) async {

var directory = Platform.isAndroid
    ? await getExternalStorageDirectory() //FOR ANDROID
    : await getApplicationSupportDirectory();

String dir = directory.path;

File file = new File('$dir/$fileName');

if (await file.exists()) {
  OpenFile.open(file.path);
} else {
  Utils.showLoaderDialogwithTitle(context, "Downloading...");

  HttpClient httpClient = new HttpClient();

  try {
    var request = await httpClient.getUrl(Uri.parse(url));
    var response = await request.close();
    print(response.statusCode);
    if (response.statusCode == 200) {
      var bytes = await consolidateHttpClientResponseBytes(response);
      print(file.path);
      await file.writeAsBytes(bytes);
    }
    Navigator.pop(context);
  } catch (ex) {
    Navigator.pop(context);
    print(ex.toString());
    Utils.displayToast(context, ex.toString());
  } finally {
    OpenFile.open(file.path);
  }
}}
Related