petek
petek

Reputation: 1088

Download file from url, save to phones storage

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.

Upvotes: 49

Views: 161829

Answers (6)

Luke Hutchison
Luke Hutchison

Reputation: 9230

You can use flutter_cache_manager and then simply do this:

await DefaultCacheManager().getSingleFile(url)

It will download the file to a cache, and return the file. The cache should be cleaned up over time (I don't know what the cache eviction policies are).

You get the benefit that trying to download the same file again returns it immediately from the cache.

Upvotes: 0

westdabestdb
westdabestdb

Reputation: 4648

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 not well maintained. Try this one https://pub.dev/packages/flowder

Upvotes: 32

Kalyan Chandra
Kalyan Chandra

Reputation: 189

 Future<String?> _saveFileToDevice(String filename, List<int> data) async {
// Get the path to the app's documents directory
var status = await Permission.storage.status;
if (!status.isGranted) {
  await Permission.storage.request();
}

var dir = Platform.isAndroid
    ? '/storage/emulated/0/Download'
    : (await getApplicationDocumentsDirectory()).path;

// Create the file and write the data to it
var file = File('$dir/$filename');

bool alreadyDownloaded = await file.exists();

String incrementCount(String fileName) {
  int dotIndex = fileName.lastIndexOf('.');
  String newFileName = fileName.substring(0, dotIndex) +
      "(${count += 1})" +
      fileName.substring(dotIndex);

  return newFileName;
}

if (alreadyDownloaded) {
  String newFileName = incrementCount(file.path);

  var newFile = File('$newFileName');
  await newFile.writeAsBytes(data, flush: true);

  String subStringFileName = newFileName.substring(29);
  CommonWidgets.makeToast(
      fontSize: 14,
      toastMsg: '${subStringFileName} saved to Downloads Folder');

  file = newFile;
  print('modified updating ....--> $file');
} else {
  await file.writeAsBytes(data, flush: true);

  CommonWidgets.makeToast(
      fontSize: 14,
      toastMsg: '${filename} saved to Downloads Folder');
}

return 'file://${file.path}';
}

This function will download the Uint8List bytes-> Which we have to convert file into Uint8List Bytes

Upvotes: -1

Jithin Jude
Jithin Jude

Reputation: 920

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;
}

Upvotes: 19

Murat Kurbanov
Murat Kurbanov

Reputation: 837

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" />

Upvotes: 17

Fabusuyi012
Fabusuyi012

Reputation: 81

FlutterChina's Dio seems like the way to go. https://github.com/flutterchina/dio/. It's robust and gives you options to retrieve the progress of your download/upload

Upvotes: 7

Related Questions