Here is the step-by-step solution to download files in the flutter web view app.
Flutter web view does not allow downloading files and images directly same as a browser. Because your web view app should have storage access permission.
You may be using the webview_flutter or flutter_inappwebview plugin solution will be the same for both you will be getting a callback of the download request.
We will be using the following plugins to achieve download functionality in the flutter web view app :
android_path_provider (to access file storage path in android)
flutter_downloader (to listen to the download event and start download)
permission_handler ( for handling permissions)
path_provider ( for accessing storage path /directory)
Now please add the latest versions of the above plugins to your pubspec.yaml file or else run the following command in your terminal :
flutter pub add android_path_provider
flutter pub add flutter_downloader
flutter pub add permission_handler
flutter pub add path_provider
Initialize flutter FlutterDownloader in main.dart file :
await FlutterDownloader.initialize(
debug: false, // optional: set to false to disable printing logs to console (default: true)
ignoreSsl : true // option: set to false to disable working with http links (default: false)
);
Inside android> app >src > main > AndroidManifest.xml :
Add these permissions to the manifest file :
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Inside tag of the manifest file add the following code :
<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="${applicationId}.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
now create a download_helper_functions.dart file and create these functions in that file :
late String localPath;
Future<void> prepareSaveDir() async {
localPath = (await findLocalPath())!;
final savedDir = Directory(localPath);
bool hasExisted = await savedDir.exists();
if (!hasExisted) {
savedDir.create();
}
return ;
}
Future<String?> findLocalPath() async {
var externalStorageDirPath;
if (Platform.isAndroid) {
try {
externalStorageDirPath = await AndroidPathProvider.documentsPath;
} catch (e) {
final directory = await getExternalStorageDirectory();
externalStorageDirPath = directory?.path;
}
} else if (Platform.isIOS) {
externalStorageDirPath =
(await getApplicationDocumentsDirectory()).absolute.path;
}
return externalStorageDirPath;
}
now inside you webview widget declaration or InAppWebView widget we have a callback onDownloadStart or onDownloadStartRequest so add this code to the download callback :
onDownloadStartRequest: (controller, DownloadStartRequest request) async {
//todo download catelog here
FlutterDownloader.registerCallback(downloadCallback);
final platform = Theme.of(context).platform;
bool value = await _checkPermission(platform);
if(value){
await prepareSaveDir();
{
final taskId = await FlutterDownloader.enqueue(
url: request.url.toString(),
savedDir: localPath,
showNotification: true,
saveInPublicStorage: true,// show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
}
}
},
and now inside your dart where you have declared webview create these two functions :
Future<bool> _checkPermission(platform) async {
if (Platform.isIOS) return true;
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
if (platform == TargetPlatform.android &&
androidInfo.version.sdkInt! <= 28) {
final status = await Permission.storage.status;
// final status2 = await Permission.manageExternalStorage.status;
if (status != PermissionStatus.granted) {
final result = await Permission.storage.request();
// final result2 = await Permission.manageExternalStorage.request();
if (result == PermissionStatus.granted) {
return true;
}
} else {
return true;
}
} else {
return true;
}
return false;
}
static void downloadCallback(
String id, DownloadTaskStatus status, int progress) {
final SendPort send =
IsolateNameServer.lookupPortByName('downloader_send_port')!;
send.send([id, status, progress]);
}
Now rebuild your app and test. download files will work now.
Hope this will help.
Feel free to ask doubt (if any in the comment section).
It takes a lot of time and effort to write solutions please upvote if this helps.