I am making flutter web app that should generate a file from user data. And have the option to download the output file.
But I can not find any options/packages which works for flutter web :(
Can someone please help me out?
I am making flutter web app that should generate a file from user data. And have the option to download the output file.
But I can not find any options/packages which works for flutter web :(
Can someone please help me out?
Simple Code for redirecting to download URL
import 'dart:html' as html;
void downloadFile(String url) {
html.AnchorElement anchorElement = new html.AnchorElement(href: url);
anchorElement.download = url;
anchorElement.click();
}
you can use package url_launcher with url_launcher_web
then you can do:
launchUrl(Uri.parse("data:application/octet-stream;base64,${base64Encode(yourFileBytes)}"));
EDIT: you don't need a plugin if you do this
download.dart:
import 'dart:convert';
// ignore: avoid_web_libraries_in_flutter
import 'dart:html';
void download(
List<int> bytes, {
String downloadName,
}) {
// Encode our file in base64
final _base64 = base64Encode(bytes);
// Create the link with the file
final anchor =
AnchorElement(href: 'data:application/octet-stream;base64,$_base64')
..target = 'blank';
// add the name
if (downloadName != null) {
anchor.download = downloadName;
}
// trigger download
document.body.append(anchor);
anchor.click();
anchor.remove();
return;
}
empty_download.dart:
void download(
List<int> bytes, {
String downloadName,
}) {
print('I do nothing');
}
import and use:
import 'empty_download.dart'
if (dart.library.html) 'download.dart';
void main () {
download('I am a test file'.codeUnits, // takes bytes
downloadName: 'test.txt');
}
dart.library.html
is not available. The 1st 2 lines of the last part has to read together:import 'empty_download.dart' if (dart.library.html) 'download.dart';
–
Mako One way to trigger download is the adapt a common pattern used in "native" javascript, create an anchor element with the download
attribute and trigger a click.
import 'dart:convert';
import 'dart:html';
main() {
File file = // generated somewhere
final rawData = file.readAsBytesSync();
final content = base64Encode(rawData);
final anchor = AnchorElement(
href: "data:application/octet-stream;charset=utf-16le;base64,$content")
..setAttribute("download", "file.txt")
..click();
}
I've found a solution that let me make an authorized request to get a file (with package http.dart) and then download the file using flutter web (with package dart:html). I don't know if someone other could need this, but I wasn't able to find a solution, so here is the code.
import 'package:http/http.dart';
import 'dart:html' as html;
...
var headers = {
'Content-Type': 'application/octet-stream',
'Accept': 'application/octet-stream',
'Authorization' : 'Bearer [TOKEN HERE]'
};
Response res =
await get(url, headers: headers);
if (res.statusCode == 200) {
final blob = html.Blob([res.bodyBytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = filename;
html.document.body.children.add(anchor);
anchor.click();
html.document.body.children.remove(anchor);
html.Url.revokeObjectUrl(url);
}
A good workaround is to open the hosted file in a new tab using
import 'dart:html' as html;
openInANewTab(url){
html.window.open(url, 'PlaceholderName');
}
Fits well for my use case.
Flutter 3.22 and WebAssembly support announced in Google IO.
The solution above WILL NOT compile to WebAssembly for 'dart:html' is deprecated now. (source:https://docs.flutter.dev/platform-integration/web/wasm#js-interop-wasm). I updated my solution to their proposal using 'package:web':
import 'package:web/web.dart';
import 'package:flutter/foundation.dart';
void myPluginDownload(String url) {
// when building in release the file structure changes ...
if (kReleaseMode) {
url = "assets/$url";
}
HTMLAnchorElement()
..href = url
..download = url
..click();
}
Cheers!
I've used the followig to download file from a URL,
import 'dart:html' as html;
void downloadFileFromDownloadableLink(String url, String fileName) {
html.AnchorElement anchorElement = html.AnchorElement(href: url);
anchorElement.download = fileName;
anchorElement.click();
}
Import html
import 'dart:html' as html;
Now Give link to your asset PDf file and name
html.window.open("assets/resume/fayyaz_resume.pdf", "fayyaz_resume.pdf");
Response to bounty:
the case of an audio file it just starts playing rather than downloading it
I've done same thing with video, but I'm sure it will work with audio as well. I assume, your generated audio is an array or blob
import 'dart:js' as JS;
import 'dart:html' as HTML;
const mimeType = 'audio/wav'; // TODO: Pick a right format
void downloadFile(List chunks) async {
final blob = HTML.Blob(chunks, mimeType);
final objectUrl = await HTML.Url.createObjectUrlFromBlob(blob);
final a = HTML.AnchorElement();
a.href = item.url;
a.download = "my_audio_file_${DateTime.now()}.wav";
HTML.document.body.append(a);
a.click();
// Wait for click event to be processed and cleanup
await Future.delayed(Duration(milliseconds: 100));
a.remove();
HTML.Url.revokeObjectUrl(item.videoObjectUrl);
}
http://www.example.com/my_audio.mp3
? –
Cady a.download
the desired custom file name? –
Granados For me, vishwajit76's answer work for me. If you want the file to have a custom name once is downloaded then do the following
`void downloadFile(String url) {
html.AnchorElement anchorElement = html.AnchorElement(href: url);
anchorElement.download = "myDocument.pdf"; //in my case is .pdf
anchorElement.click();
}`
All other solutions are correct but this solutions may disclose your storage path structure. Because downloaded file name includes complete path name of the file. If your path has uid number of firebase users, this may also cause a security breach. This may be an extreme example but it is a good practice to use uid numbers as on file path to create a more secure storage. You can create a temporary download folder as (Download/useremail) on root and copy the file intended to download inside of (Download/useremail) as below node.js code by firebase functions. This function is called when user click the download button from client. You can delete the temporary download folder later.
const functions = require("firebase-functions");
const {Storage} = require("@google-cloud/storage");
const storage = new Storage();
exports.downloadFile = functions.https.onCall(async (data, context)=> {
await storage.
bucket("my-bucket-name").
file(data.filePath).
copy(storage.
bucket("my-bucket-name").
file(`Download/${data.useremail}/${data.fileName}`));
});
This is how I implemented file download for flutter web. Note that it infers the mime type from the filename or contents which allows downloading any file type.
Create a download file named download.dart
with the following contents.
import 'dart:convert';
import 'package:logger/logger.dart';
import 'package:http/http.dart' as http;
import 'package:universal_html/html.dart' as universal_html;
import 'package:mime/mime.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
var logger = Logger(
printer: PrettyPrinter(),
);
Future<void> downloadFile(
{required String url, required String fileName}) async {
const storage = FlutterSecureStorage();
String? token = await storage.read(key: 'jwt');
try {
Map<String, String> headers = {
'Content-Type': 'application/octet-stream',
'Accept': 'application/octet-stream',
"Authorization": "Bearer $token",
};
final dataType = lookupMimeType(fileName);
final http.Response r = await http.get(Uri.parse(url), headers: headers);
final data = r.bodyBytes;
final base64data = base64Encode(data);
final a =
universal_html.AnchorElement(href: 'data:$dataType;base64,$base64data');
a.download = fileName;
a.click();
a.remove();
} catch (e) {
logger.d(e);
}
}
Call it like this.
import 'package:myproject/ui/shared/download.dart' as download;
-----
bool firstPress = true;
-----
final downloadFileButton = Expanded(
child: FilledButton(
child: Container(
padding: const EdgeInsets.all(12.0),
child: const Text(
'Download File',
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
),
onPressed: () {
if (firstPress) {
firstPress = false;
final url = 'my download url';
final fileName = 'my filename';
download.downloadFile(url: url, fileName: fileName);
}
},
),
);
( For Flutter Web only )
( Note: url is just path of your file in assets, Example: /assets/documents/fileName.pdf
)
While working on project:
import 'dart:html';
void downloadFile(String url) {
AnchorElement anchorElement = AnchorElement(href: url);
anchorElement.download = "fileName";
anchorElement.click();
}
Above code will only work in development and not in release version (Hosted project). Hosted project will give you .html
file to download.
Release version:
import 'dart:html' as html;
import 'dart:ui_web' as ui;
void downloadFile(String url) {
AnchorElement anchorElement =
AnchorElement(href: ui.AssetManager().getAssetUrl(url));
anchorElement.download = "fileName";
anchorElement.click();
}
Above code will only work in release version and not in development version.
Explanation:
The solution for the web is to use the AssetManager to retrieve the correct URL of the asset 'assets/documents/fileName.pdf'
.
Since flutter build web put all the assets/
folders into another assets folder in the tree.
So solution is to use first code while building and testing and use second code when it is time to build the web app.
If you want know more about this issue, here is the GitHub link: https://github.com/flutter/flutter/issues/126752#issuecomment-1550481365
You could also use the dio plugin, which supports this sort of thing out of the box. So you could just do:
response = await dio.download('url-to-downloadable', 'path-to-save-to');
And here's their API docs for the same.
© 2022 - 2025 — McMap. All rights reserved.
dart:html
plugins that the answers below have. – Cady