How to save and download text file in Flutter web application - flutter

I am new to Flutter and working in a flutter web application, My requirement is to create and download a text file. like below.
void getData() {
List<int> bytes = utf8.encode('this is the text file');
print(bytes); // Need to download this with txt file.
}
Can anyone help me to achieve this

This method is based on manipulations with an HTML document.
Some additional packages should be imported:
import 'dart:convert';
import 'dart:html' as html; // or package:universal_html/prefer_universal/html.dart
Code snippet:
final text = 'this is the text file';
// prepare
final bytes = utf8.encode(text);
final blob = html.Blob([bytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'some_name.txt';
html.document.body.children.add(anchor);
// download
anchor.click();
// cleanup
html.document.body.children.remove(anchor);
html.Url.revokeObjectUrl(url);
Here is DartPad demo.

Got another way to do it, via popular JS library called FileSaver
First, update your ProjectFolder/web/index.html file to include the library and define the webSaveAs function like so:
...
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js">
</script>
<script>
function webSaveAs(blob, name) {
saveAs(blob, name);
}
</script>
<script src="main.dart.js" type="application/javascript"></script>
...
Then you can call this function from Dart code like so:
import 'dart:js' as js;
import 'dart:html' as html;
...
js.context.callMethod("webSaveAs", [html.Blob([bytes]), "test.txt"])

If you are looking to simply save a text file, this method is more straight forward than having to deal with all those conversions:
import 'dart:convert' show utf8;
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' show AnchorElement;
void saveTextFile(String text, String filename) {
AnchorElement()
..href = '${Uri.dataFromString(text, mimeType: 'text/plain', encoding: utf8)}'
..download = filename
..style.display = 'none'
..click();
}
You can change the mimeType and encoding as you see fit. For instance, I had to generate CSV files in a recent project, so I used mimeType: 'text/csv'.

This solution uses FileSaver.js library and it should open the "saveAs" dialog.
I hope it works as intended:
import 'dart:js' as js;
import 'dart:html' as html;
...
final text = 'this is the text file';
final bytes = utf8.encode(text);
final script = html.document.createElement('script') as html.ScriptElement;
script.src = "http://cdn.jsdelivr.net/g/filesaver.js";
html.document.body.nodes.add(script);
// calls the "saveAs" method from the FileSaver.js libray
js.context.callMethod("saveAs", [
html.Blob([bytes]),
"testText.txt", //File Name (optional) defaults to "download"
"text/plain;charset=utf-8" //File Type (optional)
]);
// cleanup
html.document.body.nodes.remove(script);

I stumbled upon this and hardly found anything but this worked for me as of the latest flutter version 2.5.0.
you have to add this script in the body of your web/index.html file
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.21.15/plugins/export/libs/FileSaver.js/FileSaver.min.js"></script>
and then just use this method to download any type of file
import 'dart:html' as html;
import 'dart:js' as js;
void save(Object bytes, String fileName) {
js.context.callMethod("saveAs", <Object>[
html.Blob(<Object>[bytes]),
fileName
]);
}
e.g I wanted to download a JSON response from the server so I called it like this.
save(json.encode(response.data), 'file.json');
With this method you can almost download any type of file, I did use this method to download images and JSON files and it is pretty straightforward.

Related

Flutter Web - Save ui.Image to png File

I need some help with my code, I use the
"FilePicker.platform.saveFile()"
function to get the path on Windows Version (but not works on Web) and then
"final imageFuture = await controller
.renderImage(backgroundImageSize)
.then<Uint8List?>((ui.Image image) => image.pngBytes);
final imgFile = File(path);
imgFile.writeAsBytesSync(imageFuture!);
"
to save my image to disk, this works perfectly on Windows, but not on the web version.I need an alternative to save ui.Image (web Version) to PNG File on disk. 🙏🙏
I was able to solve my problem only, however the solution works only in release mode (after the build process).
import 'dart:html' as html;
import 'dart:js' as js;
final backgroundImageSize = Size(backgroundImage!.width.toDouble(),
backgroundImage!.height.toDouble());
final imageFuture = await controller
.renderImage(backgroundImageSize)
.then<Uint8List?>((ui.Image image) => image.pngBytes);
(imageFuture != null)
? js.context.callMethod(
"saveAs",
[
html.Blob([imageFuture]),
'output-image.png',
],
)
: print('Image is null');
It is necessary to add inside your web/index.html file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.21.15/plugins/export/libs/FileSaver.js/FileSaver.min.js"></script>

Flutter Web: Show PDF or Any File from Assets on another browser tab or window

Recently, I was working on the portfolio website where I need to show the user's CV which was in the PDF format on another tab.
Since this was a standalone Web Project, I didn't want to handle PDF viewing for iOS and Android.
First, you need to install this package: universal_html
flutter pub add universal_html
import the package in your file
import 'package:universal_html/html.dart' as html;
And here is the method:
Future<void> showCV() async {
var bytes = await rootBundle.load("assets/files/cv.pdf"); // location of your asset file
final blob = html.Blob([bytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
html.window.open(url, "_blank");
html.Url.revokeObjectUrl(url);
}
Voila !
var bytes = await rootBundle.load("assets/files/cv.pdf"); // location of your
asset file
final blob = html.Blob([bytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
html.window.open(url, "_blank");
html.Url.revokeObjectUrl(url);
Does it work in web hosting also ? because in my case this code is working in local host but not in web host.

Flutter web: Store a CSV file to Firebase Storage without uploading it from the computer

I'm trying to transform a Flutter mobile application into to a Flutter web application. In the Flutter application I generated a csv file, stored it in the memory of the phone and then uploaded it to Firebase storage, here is a snippet of the relevant code:
//relevant imports:
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:csv/csv.dart';
//relevant code
Future writeCSV(..) async{
final _storage = FirebaseStorage.instance;
List<List> names = [];
//...
//Store data in the list 'names'
//....
final directory = await path_provider.getExternalStorageDirectory();
File file = await File('${directory.path}/data.csv').create();
String csv = const ListToCsvConverter().convert(names);
await file.writeAsString(csv);
var snapshot = await _storage.ref().child('data2.csv').putFile(file).onComplete;
}
How could one go about this in Flutter web? When I tried to search for solutions, I could only find examples where you uploaded the file from the computer, but I would like to generate the file directly and then upload it to Firebase storage
I was able to do this in the following manner:
import 'dart:html';
import 'package:firebase/firebase.dart' as fb;
//..
//..
String data = 'name,city,age\nSimon,London,30\nJohn,New York,40';
final path = 'data.csv';
var file_contents = <String>[data];
var blob = Blob(file_contents, 'text/csv', 'native');
fb.storage().refFromURL('gs://<name>.appspot.com/')
.child(path).put(blob);

Flutter Web download file from url instead of opening it

Is there any way to get files like .pdf downloaded directly on user's device instead of opening this pdf in the browser?
This code works for downloading non browser supported files but it opens pdf, mp3, etc. in the browser.
final anchor = AnchorElement(
href: pickedFile)
..setAttribute("download", fileName)
..click();
If someone is still searching for solution.Here is what I have done.
Anchor tag will directly download file if it has download attribute.
Note: Download attribute is only supported for same-origin request
So instead of assigning external URL link to anchor element. Create Blob object from PDF data and create Object URL from that.
var url = Url.createObjectUrlFromBlob(Blob([data]));
AnchorElement(href: url)
..setAttribute('download', '<downloaded_file_name.pdf>')
..click();
I am using Firebase to store file so here is the complete code.
FirebaseStorage.instance.ref(resumeFileName).getData().then(
(data) {
var url = Url.createObjectUrlFromBlob(Blob([data]));
AnchorElement(href: url)
..setAttribute('download', '<downloaded_file_name.pdf>')
..click();
}
);
by following the steps below, you can download the file automatically by the browser and save it in the download directory.
In this method, http and universal_html packages are used.
The important thing is to manage Multiplatform-Mode and using this code, is better you create 3 separate dart files.
switch_native_web.dart
web.dart
native.dart
/// switch_native_web.dart
import 'native.dart' if (dart.library.html) 'web.dart' as switch_value;
class SwitchNativeWeb {
static void downloadFile({required String url,
required String fileName ,required String dataType}){
switch_value.downloadFile(dataType: dataType,fileName: fileName,url: url);}
}
...
/// web.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:universal_html/html.dart' as universal_html;
Future<void> downloadFile(
{required String url,
required String fileName,
required String dataType}) async {
try {
// first we make a request to the url like you did
// in the android and ios version
final http.Response r = await http.get(
Uri.parse(url),
);
// we get the bytes from the body
final data = r.bodyBytes;
// and encode them to base64
final base64data = base64Encode(data);
// then we create and AnchorElement with the html package
final a =
universal_html.AnchorElement(href: '$dataType;base64,$base64data');
// set the name of the file we want the image to get
// downloaded to
a.download = fileName;
// and we click the AnchorElement which downloads the image
a.click();
// finally we remove the AnchorElement
a.remove();
} catch (e) {
print(e);
}
}
...
/// native.dart
Future<void> downloadFile({required String url, required String fileName,
required String dataType}) async {}
And using the following sample code for calling the downloadFile method wherever you need:
...
GestureDetector(
onTap: () => SwitchNativeWeb.downloadFile(
url: "https://... your url ..../download.jpg",
fileName: "download.jpg",
dataType: "data:image/jpeg"),
child: Text('download')
)
...
I only wrote the code related to web download (according to the question), you can write the code related to ios and android download in the native .dart file.
Use Dio Library.
dependencies:
dio: ^3.0.10
to download file
response = await dio.download("https://www.google.com/", "./xx.html");
this video will help you.

Flutter how to Convert filePath from content://media/external/images/media/5275 to /storage/emulated/0/DCIM/Camera/IMG_00124.jpg

I have URI LIKE below
content://media/external/images/media/5275
but I want convert it to Like format below:
/storage/emulated/0/DCIM/Camera/IMG_00124.jpg
Anyone who can help me!
Sreng Bona
Thanks!
var path = await FlutterAbsolutePath.getAbsolutePath("content://media/external/images/media/5275");
Add this flutter_absolute_path: ^1.0.6 to your file: pubspec.yaml
It will be working as Well.
Bona SR.
I had to search a lot, but I found a very useful solution to save the image in the cell phone's photo gallery and get the absolute path to use it the way you want.
For this example I used a result obtained from saving an image in the photo gallery, however it could also work to read other files, obviously making the changes that you see necessary, I hope it will help you
uri_to_file
image_gallery_saver
import 'dart:io';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:uri_to_file/uri_to_file.dart';
Future<File> saveImage(File image, String identifier) async {
try {
var result = await
ImageGallerySaver.saveImage(image.readAsBytesSync(),
quality: 60, name: identifier +
"-${DateTime.now().toIso8601String()}");
print(result);
File file = await toFile(Uri.parse(result['filePath']));
print(file);
return file;
} catch (e) {
print(e);
return new File('assets/img/default-img.jpg');
}
}
// example
saveImage(File("path/image.jpg"),"img-test");