I am building a flutter web using old version. I am having a FileUploadInputElement. I need to get the file selected from that element.
#override
Widget build(BuildContext context) {
FileUploadInputElement fileUploadInputElement = FileUploadInputElement();
ui.platformViewRegistry.registerViewFactory(
'animation-Image-html', (int viewId) => fileUploadInputElement);
return SizedBox(
child: HtmlElementView(
viewType: 'animation-Image-html',
),
);
}
You can directly use the element.files property to access the files and use the Filreader class from dart:html. I have created an example below to show you how a text file and image can be read. This example is based on FileReader examples in another post.
Accessing the file
Here element is the FileUploadInputElement reference.
element.files[0] or in case of multiple files element.files
Set up your file reader
String option1Text = "Initialized text option1";
Uint8List uploadedImage;
FileUploadInputElement element = FileUploadInputElement()..id = "file_input";
// setup File Reader
FileReader fileReader = FileReader();
Use FileReader to read the file
fileReader.readAsText(element.files[0])
connect the listener for load event
fileReader.onLoad.listen((data) {
setState(() {
option1Text = fileReader.result;
});
});
connect error events
fileReader.onError.listen((fileEvent) {
setState(() {
option1Text = "Some Error occured while reading the file";
});
});
Use Image.memory to show images from byte array.
Image.memory(uploadedImage)
Note: In the following example we choose a file and click the respective button to handle the file reading. But the same can be achieved by connecting the logic in respective events of the FileUploadInputElement element in a similar approach. eg: element.onLoad.listen or element.onError.listen event streams.
Full Example
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:html';
class FileUploadTester extends StatefulWidget {
#override
_FileUploadTesterState createState() => _FileUploadTesterState();
}
class _FileUploadTesterState extends State<FileUploadTester> {
String option1Text = "Initialized text option1";
Uint8List uploadedImage;
FileUploadInputElement element = FileUploadInputElement()..id = "file_input";
// setup File Reader
FileReader fileReader = FileReader();
// reader.onerror = (evt) => print("error ${reader.error.code}");
#override
Widget build(BuildContext context) {
ui.platformViewRegistry.registerViewFactory("add_input", (int viewId) {
return element;
});
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
FlatButton(
color: Colors.indigoAccent,
child: Text('ReadFile'),
onPressed: () {
fileReader.onLoad.listen((data) {
setState(() {
option1Text = fileReader.result;
});
});
fileReader.onError.listen((fileEvent) {
setState(() {
option1Text = "Some Error occured while reading the file";
});
});
fileReader.readAsText(element.files[0]);
},
),
Expanded(
child: Container(
child: Text(option1Text),
),
),
Expanded(child: HtmlElementView(viewType: 'add_input')),
Expanded(
child: uploadedImage == null
? Container(
child: Text('Uploaded image should shwo here.'),
)
: Container(
child: Image.memory(uploadedImage),
),
),
FlatButton(
child: Text('Show Image'),
color: Colors.tealAccent,
onPressed: () {
fileReader.onLoad.listen((data) {
setState(() {
uploadedImage = fileReader.result;
});
});
fileReader.onError.listen((fileEvent) {
setState(() {
option1Text = "Some Error occured while reading the file";
});
});
fileReader.readAsArrayBuffer(element.files[0]);
},
),
],
);
}
}
Below
Image Upload in Flutter Web - Working perfectly fine for me :)
startFilePicker() async {
FileUploadInputElement uploadInput = FileUploadInputElement();
uploadInput.multiple = true;
uploadInput.draggable = true;
uploadInput.click();
uploadInput.onChange.listen((e) {
// read file content as dataURL
final files = uploadInput.files;
print(files);
if (files != null && files.isNotEmpty) {
for (var i = 0; i < files.length; i++) {
FileReader reader = FileReader();
reader.onLoadEnd.listen((e) async {
if (reader.result != null) {
Uint8List? _byteData = reader.result as Uint8List;
// upload the image
}
});
reader.onError.listen((fileEvent) {
Fluttertoast.showToast(
msg: "Some Error occured while reading the file");
});
reader.readAsArrayBuffer(files[i]);
}
} else {
Fluttertoast.showToast(msg: 'Images not selected');
}
});
}
Related
i want to upload my images to the sever from flutter web, which is using graphql api. i am able to show the images on the web but unable to upload images to the server.
static Future<int> multipartApi(File file)async {
print("image_file_path=${file.path}");
var byteData = file.readAsBytesSync();
var multipartFile = MultipartFile.fromBytes(
"",
byteData,
filename: "${DateTime.now().second}.jpeg",
contentType: MediaType("image", "jpeg"),
);
here i am picking images from gallery
final picker = ImagePicker();
List<Uint8List> images = []; // <----change this
List<Uint8List> imageFiles = [];
List<File> imageList = [];
List<int> my_images = [];
pickImage(BuildContext context) async {
List<XFile>? files = await picker.pickMultiImage(imageQuality: 50);
if (files != null) {
for (var element in files) {
imageList.add(File(element.path));
print("imageList= ${imageList.first.path}");
html.File filePath = html.File(element.path.codeUnits, element.path);
print("filePath: ${filePath.toString()}");
imageFiles.add(await element.readAsBytes());
}}
// for (var element in files!) {
// imageList.add(File(element.path));
//
// imageFiles.add(await element.readAsBytes()); // <----change this
// }
print("image path: ${imageList}");
print("Length of images: ${imageList.length}");
setState(() {
images = imageFiles;
print("selected_images: ${images.first.toString()}");
});
print("list length: ${images.length}");
}
and here i am displaying my images inside listview builder.
child: ListView.builder(
itemCount: images.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Image.memory(
images[index],
height: 80,
width: 80,
),
InkWell(
onTap: () {
setState(() {
images.remove(images[index]);
});
},
child: const Icon(Icons.close),
),
],
);
},
),
tell me where i am wrong.
"images":[
{
"id":11,
"imageName":"xCh-rhy"
},
{
"id":31,
"imageName":"fjs-eun"
} ];
Try this,
Create model,
class Image {
final String id;
final String name;
Images({this.id, this.name});
}
Parse & Add Data,
List<Image> parsedImages = [];
List<dynamic> jsonImages = jsonData["images"];
jsonImages.forEach(
(imgInfo) {
parsedImages.add(
Image(
id: imgInfo["id"],
name: imgInfo["imageName"],
)
);
}
);
Build List,
ListView.builder(
itemBuilder: (context, index) {
return ListTile(title: Text(parsedImages.name));
},
itemCount: parsedImages.length,
)
I have a ListView which holds ListTiles. Each tile represents a user of my users array. The trailing of a tile is a PopupMenuButton. When the user clicks on one PopupMenuItem, a function shall be called. So far so good. In the "onSelected" I would like to pass data of the corresponding user to a function.
Could anybody please give me a hint, how I should change the code to be able to do so?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:flutter/material.dart';
class UserListMobilePortrait extends StatelessWidget {
final List<QueryDocumentSnapshot> users;
const UserListMobilePortrait({
Key key,
this.users,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final HttpsCallable setRoleCallable = CloudFunctions.instance
.getHttpsCallable(functionName: 'setRoles')
..timeout = const Duration(seconds: 10);
final button = new PopupMenuButton(
itemBuilder: (_) => <PopupMenuItem<String>>[
new PopupMenuItem<String>(
child: const Text('Make Admin'), value: 'admin'),
new PopupMenuItem<String>(
child: const Text('Make Editor'), value: 'editor'),
],
onSelected: (selectedItem) async {
try {
final HttpsCallableResult result = await setRoleCallable.call(
<String, dynamic>{
//'user' shall represent the user of the clicked ListTile, but how to pass it?
'email': user.data()['email'],
'role': selectedItem,
'permission': 'grant'
},
);
print(result.data);
} on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
} catch (e) {
print('caught generic exception');
print(e);
}
});
return ListView(
children: users
.map((user) => ListTile(
title: Text(
(user.data()['email'] != null) ? user.data()['email'] : ""),
subtitle: Row(
children: [
Text((user.data()['displayName'] != null)
? user.data()['displayName']
: ""),
Container(
width: 6,
),
user.data()['isAdmin'] == true
? Chip(
label: Text('admin'),
backgroundColor: Colors.orange[600],
shadowColor: Colors.orange[900],
)
: Text(''),
Container(
width: 6,
),
user.data()['isEditor'] == true
? Chip(
label: Text('editor'),
backgroundColor: Colors.blue[600],
shadowColor: Colors.blue[900],
)
: Text(''),
],
),
trailing: button,
))
.toList(),
);
}
}
understanding your problem a simple workaround will be to use a Listview Builder(And also using a ListView Builder will optmize the app for speed)
const List = ["Hello", "World", "Temp"]
ListView.builder(
itemBuilder: (context, index) {
//return (Your widget [a list tile preferably and use onTap(and access the index
in the function)])
return(ListTile(onTap:(){
print(List[index]);
//you can access the index and use the main list to get its following data
};
};
This will workout :)
My solution was moving the former final button to its own class. So I can pass the data to the constructor.
UserPopupMenuButton
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:flutter/material.dart';
class UserPopupMenuButton extends StatelessWidget {
final QueryDocumentSnapshot user;
const UserPopupMenuButton({
Key key,
this.user,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final HttpsCallable setRoleCallable = CloudFunctions.instance
.getHttpsCallable(functionName: 'setRoles')
..timeout = const Duration(seconds: 10);
return PopupMenuButton(
itemBuilder: (_) => <PopupMenuItem<String>>[
new PopupMenuItem<String>(
child: const Text('Make Admin'), value: 'admin'),
new PopupMenuItem<String>(
child: const Text('Make Editor'), value: 'editor'),
],
onSelected: (selectedItem) async {
try {
final HttpsCallableResult result = await setRoleCallable.call(
<String, dynamic>{
'email': user.data()['email'],
'role': selectedItem,
'permission': 'grant'
},
);
print(result.data);
} on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
} catch (e) {
print('caught generic exception');
print(e);
}
});
}
}
And using it as the trailing for the ListTile:
trailing: UserPopupMenuButton(user: user),
I want to read the data from a .txt file in FLutter, it contains just a number. I use the functions from the official documentations(https://flutter.dev/docs/cookbook/persistence/reading-writing-files), of course modified them a bit to fit in my program:
class _InClassRoomState extends State<InClassRoom> {
#override
var pontsz = readpontok().toString();
void initState() {
super.initState();
}
Future<String> readpontok() async {
try {
final file = await _localFile;
// Read the file.
String contents = await file.readAsString();
return await contents;
} catch (e) {
// If encountering an error, return 0.
return null;
}
}
The respecting part of my widget tree is the body of the Scaffold:
body: Center(
child: Text(
pontsz.toString(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 50,
color: Colors.black,
),
),
),
But when I run the code it just writes "Instance of Future in the body of the scaffold. Why?
You are passing a Future to the string. you should call readpontok() from initState() and setState pontsz = content
class _InClassRoomState extends State<InClassRoom> {
// create pontsz variable
var pontsz;
#override
void initState() {
super.initState();
// call the function
readpontok();
}
Future readpontok() async {
try {
final file = await _localFile;
// Read the file.
String contents = await file.readAsString();
setState(() {
pontsz = contents;
});
} catch (e) {
// If encountering an error, display Error
setState(() {
pontsz = "Error";
});
}
}
}
i want to display the questions i get from an API one by one. I call the API, parse and store the data, but i don't know how to display each question separately. I can put them in a list view but that's about it. I have a widget with FutureBuilder that calls the API, and i'm currently trying to send data to another widget and manipulate it there using another FutureBuilder (so that i don't keep calling the API when i iterate through the list of questions to display them). I have an integer to keep track of the current position. How should i go about doing this?
Part of the code:
Here i'm trying to send the data to another widget.
FutureBuilder<Reply>(
future: questions(token, id),
builder: (context, snapshot) {
if (snapshot.hasError) {
print('Error : ${snapshot.error}'); //show error on the terminal
return Text('Error : ${snapshot.error}'); //show error on the app
} else if (snapshot.hasData) {
reply = snapshot.data;
return Show_Questions(reply: reply,);
} else {
return Center(child: CircularProgressIndicator()); //else display a loading indicator
} //loading indicator
}
),
Any help is appreciated. I can post more code if needed.
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new FutureBuilder(
future: questions(token, id),
initialData: [],
builder: (context, snapshot) {
return createListView(context, snapshot);
}),
);
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
var values = snapshot.data;
return ListView.builder(
itemCount: values == null ? 0 : values.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
setState(() {
});
},
child: Column(
children: <Widget>[
new ListTile(
title: Text(values[index]),
),
Divider(
height: 2.0,
),
],
),
);
},
);
}
}
hopefully help you :)