Implement In-App Download Feature In Flutter App Easily.

It’s not hard as it seems.

Photo by Ignacio Amenábar on Unsplash

To implement in-app downloads in a Flutter app, you need to use libraries that can handle downloading files and managing states effectively. A common choice is the dio package for making HTTP requests, along with the path_provider package to save the downloaded file in the device’s local storage.

Here’s how you can implement in-app downloads in Flutter:

Step 1: Add Dependencies

Update your pubspec.yaml file to include the required packages:

dependencies:
dio: ^5.0.0
path_provider: ^2.0.14
permission_handler: ^11.0.0

Run flutter pub get to install the dependencies.

Step 2: Request Permissions

Before downloading a file, you must ensure the app has the required permissions to write files to the device’s storage.

import 'package:permission_handler/permission_handler.dart';
Future<void> requestStoragePermission() async {
if (await Permission.storage.request().isDenied) {
// Show a message if permission is denied
print('Storage permission denied');
}
}

Step 3: Implement the Download Functionality

Use the dio package to handle the file download.

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
class Downloader {
final Dio _dio = Dio();
Future<void> downloadFile(String url, String fileName) async {
try {
// Get the directory for saving the file
final dir = await getApplicationDocumentsDirectory();
// Build the file path
final filePath = "${dir.path}/$fileName";
// Start the download
await _dio.download(
url,
filePath,
onReceiveProgress: (received, total) {
if (total != -1) {
// Show the download progress (in percentage)
print("Download Progress: ${(received / total * 100).toStringAsFixed(0)}%");
}
},
);
print("File downloaded successfully: $filePath");
} catch (e) {
print("Download failed: $e");
}
}
}

Step 4: Create a UI for the Download

Here’s an example of a simple UI to trigger the download:

import 'package:flutter/material.dart';
import 'downloader.dart';
class DownloadScreen extends StatelessWidget {
final String fileUrl = "https://example.com/sample.pdf";
final String fileName = "sample.pdf";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("In-App Download Example"),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
final downloader = Downloader();
await downloader.downloadFile(fileUrl, fileName);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Download started!")),
);
},
child: Text("Download File"),
),
),
);
}
}

Step 5: Handle Edge Cases

To make your download process robust:

  1. Network Errors: Wrap the download logic in a try-catch block to handle timeouts or connectivity issues.
  2. File Overwriting: Check if the file already exists and handle appropriately.
  3. User Feedback: Show a loading spinner or progress bar during the download process.

Step 6: Add Progress Indicators (Optional)

You can enhance the UI by displaying the progress using a progress bar.

import 'package:flutter/material.dart';
import 'downloader.dart';
class DownloadScreenWithProgress extends StatefulWidget {
@override
_DownloadScreenWithProgressState createState() => _DownloadScreenWithProgressState();
}
class _DownloadScreenWithProgressState extends State<DownloadScreenWithProgress> {
double _progress = 0.0;
Future<void> startDownload() async {
final downloader = Downloader();
await downloader._dio.download(
"https://example.com/sample.pdf",
"${(await getApplicationDocumentsDirectory()).path}/sample.pdf",
onReceiveProgress: (received, total) {
if (total != -1) {
setState(() {
_progress = received / total;
});
}
},
);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Download complete!")),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Download with Progress"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LinearProgressIndicator(value: _progress),
SizedBox(height: 20),
ElevatedButton(
onPressed: startDownload,
child: Text("Start Download"),
),
],
),
),
);
}
}

Key Considerations

  1. Permission Management: Use permission_handler to request permissions dynamically.
  2. Offline Storage: Save files to device directories using path_provider.
  3. Background Downloads: For downloads that need to continue when the app is in the background, consider using native integrations (e.g., workmanager or platform channels).

Thank You, Hope You Enjoyed.

Learn more Implement In-App Download Feature In Flutter App Easily.

Leave a Reply