Reputation: 1088
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
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
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
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
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
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
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