Flutter Pro Design

Small details that build taste in Flutter.

curated by Kamran BekirovKamran Bekirov

Save files without permission handling

A button says "Download". The usual way is to build the whole thing behind it: ask for storage permission, handle the user saying no, find the right public folder on Android, work around scoped storage, do it differently again on iOS, then hope the user can find the file later.

Almost all of that work is just to put the file into a public folder. But right after, the user usually opens it or sends it to someone. The OS already has a screen for that, the native share sheet. "Save to Files", AirDrop, Messages, Mail, WhatsApp, all in one place.

So skip the public folder. Download the bytes, save them to your app's own cache, and pass the file to the share sheet.

getTemporaryDirectory() needs no permission on any platform:

import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
import 'package:share_plus/share_plus.dart';

Future<XFile> _downloadToCache(String url, String filename) async {
  final http.Response response = await http.get(Uri.parse(url));
  
  final Directory dir = await getTemporaryDirectory();
  final File file = File('${dir.path}/$filename');
  await file.writeAsBytes(response.bodyBytes);
  
  return XFile(file.path);
}

Then open the share sheet:

Future<void> shareFile(String url) async {
  final XFile file = await _downloadToCache(url, 'invoice.pdf');
  
  await SharePlus.instance.share(
    ShareParams(files: [file]),
  );
}

That is the whole feature. No permission_handler, no folders for each platform, no "where did my file go".

"Save to Files" is the download. Right next to it is "send to a person", which is what many were going to do anyway. One screen, fewer taps.

In a real screen, wire this into your state management: show a loading state while the file downloads in the background.

The rule: if "download" really means "let me do something with this file", let the OS show the options.