Web and desktop support for file upload and download in Flutter

10 min readJul 19, 2023

Managing conditional imports and CORS issues

Uploading and downloading your cat pics

Here’s what I want to do:

  • The user chooses a file and uploads it to a server.
  • The user downloads a file and chooses where to save it.
  • Both of these tasks should support web and desktop.

The problem is, on desktop (and mobile) these operations require dart:io, which doesn’t support web. And web requires dart:http, which doesn’t support desktop.

You might think you could just import both libraries and then choose the appropriate classes and functions using kIsWeb like so:

if (kIsWeb) {
// use dart:html stuff
} else {
// use dart:io stuff

Unfortunately that doesn’t work, though, because kIsWeb is a runtime constant, and so Flutter still tries to import both libraries when it compiles your app, which results in an error. Read more about that here.

The solution is to use conditional imports. This article will take you through the steps to set that up as well as jump through a few other hurdles along the way. You’ll create a simple demo app with two buttons, one for upload and one for download:

Demo app running on Chrome and macOS

Start by creating a new Flutter project and building the UI above. If you need some help, scroll to the end of the article for the full code.

Adding conditional imports/exports

You want to perform one set of tasks if the user is running your app on the web and another set of tasks if they’re running it on the desktop (or mobile). For that, you’re going to make a FileManager class to handle the various tasks.

Setting up the project structure

In the lib folder of your project, create a sub-folder named file_manager. In that folder, add the following:

  • a folder named src
  • a file named file_manager.dart