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 whic
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();
}
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();
}
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);
}
you can use package url_launcher with url_launcher_web
then you can do:
launch("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');
}
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.