I try to make login with Flutter, Nodejs(Express), and oracle
the backend is working when I test it with POSTMAN I can get the token
here postman test
data show in cmd when I try with Postman
this image contains the data show in the flutter debugger
but the problem is
when I try to link the flutter and the node the data sent from flutter is not received in node js
the IDNUMBER and PASS have the value of undefined
means req.body.IDNUMBER=undefined and req.body.PASS=undefined
data show in cmd when I try with flutter in nodejs
I know that I'm missing something
here the flutter code
import 'dart:convert';
import 'package:app_project/homepage.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class Login extends StatefulWidget {
Login({Key? key}) : super(key: key);
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
TextEditingController _idNumberController = new TextEditingController();
TextEditingController _passController = new TextEditingController();
bool _isloading = false;
bool showpass = true;
String url = "http://192.168.1.19:3000/auth2";
signIn(String idNumber, String pass) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
Map body = {"IDNUMBER": idNumber, "PASS": pass};
var jsonResponse;
var res = await http
.post(Uri.parse(url), body: {"IDNUMBER": idNumber, "PASS": pass});
// check the api status (connection)
if (res.statusCode == 200) {
jsonResponse = await json.decode(json.encode(res.body));
print("the body is ${body}");
print("Response status 1 :${res.statusCode}");
print("Response status 2 :${res.body}");
if (jsonResponse != null) {
setState(() {
_isloading = false;
print("Response status 2 2 :${res.body}");
});
//print(jsonResponse.runtimeType);
sharedPreferences.setString("token", jsonResponse.toString());
Navigator.of(context).pushReplacementNamed("homepage");
}
} else {
setState(() {
_isloading = false;
});
print("Response status 3 :${res.body}");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset("images/1.png"),
Container(
margin: EdgeInsets.all(20),
child: Form(
child: Column(
children: [
TextFormField(
controller: _idNumberController,
cursorColor: Colors.red,
style: TextStyle(fontSize: 20),
decoration: InputDecoration(
hintText: "اكتم رقمك التسلسلي",
prefixIcon: Icon(Icons.person),
filled: true,
fillColor: Colors.orange[100],
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
borderSide:
BorderSide(color: Colors.orange, width: 3)),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
borderSide:
BorderSide(width: 1, color: Colors.orange)),
focusColor: Colors.red),
),
SizedBox(
height: 30,
),
TextFormField(
controller: _passController,
cursorColor: Colors.red,
obscureText: showpass,
style: TextStyle(fontSize: 20),
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () {
setState(() {
showpass = !showpass;
});
},
icon: showpass
? Icon(Icons.remove_red_eye_sharp)
: Icon(Icons.remove_red_eye_outlined)),
hintText: "اكتم كلمة المرور",
prefixIcon: Icon(Icons.lock),
filled: true,
fillColor: Colors.orange[100],
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
borderSide:
BorderSide(color: Colors.orange, width: 3)),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
borderSide:
BorderSide(width: 1, color: Colors.orange)),
focusColor: Colors.red),
),
SizedBox(
height: 30,
),
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(
horizontal: 35, vertical: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100))),
onPressed: () {
setState(() {
_isloading = true;
});
signIn(
_idNumberController.text, _passController.text);
print("id = ${_idNumberController.text}");
print("pass = ${_passController.text}");
},
icon: Icon(Icons.login),
label: Text("سجل الدخول"))
],
)),
)
],
)
],
),
);
}
}
here the node code post function
app.post("/auth2", async (req, res) => {
try {
connection = await oracledb.getConnection({
user: "system",
password: password,
connectString: "localhost:1521/XE"
});
console.log('connected to database');
// run query to get all employees
console.log(`the req id ${req.body.IDNUMBER}`)
console.log(`the req PASS ${req.body.PASS}`)
result = await connection.execute(`SELECT IDNUMBER,PASS FROM USERS WHERE IDNUMBER=:IDNUMBER AND PASS=:PASS`,
[req.body.IDNUMBER,req.body.PASS]
);
let ress = {
"IDNUMBER": result.rows[0][0],
"PASS":result.rows[0][1]
}
console.log({
//those variables show as undefined
"IDNUMBER": result.rows[0][0],
"PASS":result.rows[0][1]
})
if (result.rows.length != 0) {
const token = jwt.sign({ _id: ress }, 'privateKey');
console.log(token);
res.json({ token: token });
} else {
res.json({"message":"there is no one in the database has this idnumber"})
}
} catch (err) {
console.log("the information is not passing ")
return res.send(err.message)
}
})
Use jsonEncode to send your parameters.
Use headers to tell your NodeJs server that you are sending parameters.
Map<String, String> requestHeaders =
{'Content-type': 'application/json',
'Accept': 'application/json',};
var res = await http.post(Uri.parse(url),body:jsonEncode(body), headers: requestHeaders);
Related
I am trying to connect nodejs socket using Flutter socket_io_client. but It's not connecting, Server running fine. Below is server code, In flutter I used socket_io_client. There is no error, but still not connecting. I am a beginner in both socket and nodejs. Help me to find out what's the problem?
myserver.js
const socketio = require('socket.io');
const express = require('express');
const http = require('http');
const app = express();
server = app.listen(3000);
//io server
//const io = require("socket.io")(server);
//3000 or any other port.
const io = http.createServer(app);
const PORT = 3000 || process.env.PORT;
console.log(`Server running on port ${PORT}`);
var userConnection = [];
io.on('connect', (socket)=>
{
console.log(`nside connection`);
socket.on('users_info_to_signaling_server', (data) =>
{
var other_users = userConnection.filter(p=> p.meeting_id == data.meetingid);
// data saves to userConnection variable
// connection id and socket id are same
userConnection.push({
connectionId: socket.id,
user_id: data.current_user_name,
meeting_id: data.meetingid,
})
})
})
Flutter code
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _localRenderer = new RTCVideoRenderer();
final _remoteRenderer = new RTCVideoRenderer();
//final _remoteRenderer2 = new RTCVideoRenderer();
TextEditingController titleController = TextEditingController();
IO.Socket socket;
#override
void dispose() {
// TODO: implement dispose
titleController.dispose();
super.dispose();
}
#override
void initState() {
connectToServer();
super.initState();
}
void connectToServer() {
//initializing with backend server
socket = IO.io('http://localhost:3000', <String, dynamic>{
'transports': ['websocket'],
'autoConnect': false,
});
//connection to server
socket.connect();
socket.onConnect((_) {
if (socket.connected) {
print('socket connected');
socket.emit('users_info_to_signaling_server',
{"current_user_name": "abccheck", "meetingid": "testing"});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Row(
children: [
Container(
height: 210,
child: Row(
children: [
Container(
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0),
height: 200,
width: 350,
decoration: BoxDecoration(color: Colors.black),
key: Key('local'),
child: RTCVideoView(_localRenderer),
),
Container(
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0),
height: 200,
width: 350,
decoration: BoxDecoration(color: Colors.black),
key: Key('remote'),
child: RTCVideoView(_localRenderer),
),
Container(
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0),
height: 200,
width: 350,
decoration: BoxDecoration(color: Colors.black),
key: Key('remote2'),
child: RTCVideoView(_localRenderer),
),
],
),
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: titleController,
decoration: InputDecoration(
hintText: 'Name or MeetingID',
alignLabelWithHint: true,
),
),
),
SizedBox(
height: 8.0,
),
RaisedButton(
onPressed: () {},
child: Text('Host'),
),
Padding(
padding: EdgeInsets.all(8.0),
),
RaisedButton(
onPressed: () {},
child: Text('Join'),
),
],
),
);
}
}
The issue is that there are version compatibilities you need to check the documentation for your plugin like shown below
Here is my solution:
You need to write 192.168.1.x instead of localhost.
If you run Express app port 3000 then:
socket = IO.io('http://192.168.1.x:3000', <String, dynamic>{
'transports': ['websocket'],
'autoConnect': false,
});
To find out your local ip address in windows, open cmd and write ipconfig.
...
...
IPv4 Address. . . . . . . . . . . : 192.168.1.x
...
...
I'm working on a Flutter app, that consists of a employee scheduler with a Parse Server background.The app works as the following:
1)User opens the app;
2)The app shows a list of cards of available employees (if there is some in the server database)
3)The user is able to edit, confirm or delete the employee availability.
The app is working. It means that I'm able to CRUD data also from my Parse Server as from my app screen.
The goal: Every data change in the database needs to refresh (realtime) the user screen, removing, deleting or updating the (changed) data itself.
My idea: use parse_server_sdk: ^2.0.1 as a dependency (pubspec.yaml) and implement Live Queries (as the github docs here)
The Problem: after compilation, despite my AndroidStudio don't crashes visually speaking, nor my application itself, it shows me (logs) that "LiveQuery does not work, if there is ParseConnectivityProvider provided".
Without problems(main.dart):
void main() async{
runApp(MyApp());
}
Causing problems:
void main() async{
//the following parameters are in other file (constants.dart)...they are working
Parse().initialize(
kParseApplicationId,
kParseServerUrl,
masterKey: kParseMasterKey,
clientKey: kParseClientKey,
debug: true,
liveQueryUrl: kLiveQueryUrl,
autoSendSessionId: true,
);
var dietPlan = ParseObject('DietPlan')
..set('Name', 'Ketogenic')
..set('Fat', 65);
await dietPlan.save();
var response = await dietPlan.save();
if (response.success) {
dietPlan = response.result;
}
//until here, the program works well.The data is inserted and retrieved, ok...but exactly here..the problem!
final LiveQuery liveQuery = LiveQuery(); //from here..this is causing problems
QueryBuilder<ParseObject> query =
QueryBuilder<ParseObject>(ParseObject('DietPlan'))
..whereEqualTo('intNumber', 1);
Subscription subscription = await liveQuery.client.subscribe(query);
subscription.on(LiveQueryEvent.delete, (value) {
print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
print((value as ParseObject).objectId);
print((value as ParseObject).updatedAt);
print((value as ParseObject).createdAt);
print((value as ParseObject).get('objectId'));
print((value as ParseObject).get('updatedAt'));
print((value as ParseObject).get('createdAt'));
});
runApp(MyApp());
}
I didn't found any solution googleing.Any at all. After many research, I've got (going deep in the libraries) that Parse.Initialize(...) have connectivityProvider as one of it's parameters, but I didn't fill that parameter.
Also, the problems starts exactly when I've inserted the the line:
final LiveQuery liveQuery = LiveQuery();
Could someone help me to solve this issue?Thanks in advance
In the following, I'm showing all my code(main.dart):
// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:intl/intl.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:marca_horario/model/data.dart';
import 'package:marca_horario/network_utils/data_utils.dart';
import 'package:http/http.dart';
import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:marca_horario/constants.dart';
void myLQ() async {
Parse().initialize(
kParseApplicationId,
kParseServerUrl,
masterKey: kParseMasterKey,
clientKey: kParseClientKey,
debug: true,
liveQueryUrl: kLiveQueryUrl,
autoSendSessionId: true,
);
var dietPlan = ParseObject('DietPlan')
..set('Name', 'Ketogenic')
..set('Fat', 65);
await dietPlan.save();
var response = await dietPlan.save();
if (response.success) {
dietPlan = response.result;
}
final LiveQuery liveQuery = LiveQuery();
QueryBuilder<ParseObject> query =
QueryBuilder<ParseObject>(ParseObject('DietPlan'))
..whereEqualTo('intNumber', 1);
Subscription subscription = await liveQuery.client.subscribe(query);
subscription.on(LiveQueryEvent.delete, (value) {
print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
print((value as ParseObject).objectId);
print((value as ParseObject).updatedAt);
print((value as ParseObject).createdAt);
print((value as ParseObject).get('objectId'));
print((value as ParseObject).get('updatedAt'));
print((value as ParseObject).get('createdAt'));
});
}
void main() async{
Parse().initialize(
kParseApplicationId,
kParseServerUrl,
masterKey: kParseMasterKey,
clientKey: kParseClientKey,
debug: true,
liveQueryUrl: kLiveQueryUrl,
autoSendSessionId: true,
);
var dietPlan = ParseObject('DietPlan')
..set('Name', 'Ketogenic')
..set('Fat', 65);
await dietPlan.save();
var response = await dietPlan.save();
if (response.success) {
dietPlan = response.result;
}
final LiveQuery liveQuery = LiveQuery();
QueryBuilder<ParseObject> query =
QueryBuilder<ParseObject>(ParseObject('DietPlan'))
..whereEqualTo('intNumber', 1);
Subscription subscription = await liveQuery.client.subscribe(query);
subscription.on(LiveQueryEvent.delete, (value) {
print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
print((value as ParseObject).objectId);
print((value as ParseObject).updatedAt);
print((value as ParseObject).createdAt);
print((value as ParseObject).get('objectId'));
print((value as ParseObject).get('updatedAt'));
print((value as ParseObject).get('createdAt'));
});
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
supportedLocales: [const Locale('pt', 'BR')],
home: Home()
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
var _listTiles = List<String>();
Color _iconColor = Colors.black;
Color standardIconColor = Colors.black;
Color alternateIconColor = Colors.green;
TextEditingController _nameController = TextEditingController();
var _scaffoldKey = new GlobalKey<ScaffoldState>();
String standardTileTitle = "Adicione um horário disponível...";
String _titleTile = "Adicione um horário disponível...";
String _tileSubtitle = "Edite o nome do funcionário...";
int _selectedIndexBottomNavBar = 0;
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = new GlobalKey<RefreshIndicatorState>();
#override
Widget build(BuildContext context) {
return RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: () async {
setState(() {
});},
child: Scaffold(
key: _scaffoldKey,
floatingActionButton: FloatingActionButton(
onPressed: () {
invokeDatePicker();
},
child: Icon(Icons.add),
),
bottomNavigationBar: bottomNavigationBar(),
appBar: AppBar(
title: Text('Marca Horário'),
),
// body: Center(
// child: Text('Hello World'),
body: bodyStartScreen()
),
);
}
Widget bottomNavigationBar(){
void _onItemTapped(int index) {
setState(() {
_selectedIndexBottomNavBar = index;
});
print(_selectedIndexBottomNavBar);
if(_selectedIndexBottomNavBar == 2){
DatePicker.showDateTimePicker(context,
showTitleActions: true,
minTime: DateTime(2020, 1, 1),
maxTime: DateTime(2021, 12, 31),
onChanged: (date) {
print('change $date');
},
onConfirm: (date) {
print('confirm $date');
_listTiles.add(DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString());
_titleTile = DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString();
setState(() {
});
},
currentTime: DateTime.now(),
locale: LocaleType.pt);
}
}
return BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Funcionário',
),
BottomNavigationBarItem(
icon: Icon(Icons.access_time),
label: 'Marcar',
),
],
currentIndex: _selectedIndexBottomNavBar,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
);
}
Widget bodyStartScreen(){
return Column(
children: [
//the main title of the screen
Padding(
padding: EdgeInsets.all(16.0),
child: Text("Horários Possíveis",
style: TextStyle(
fontSize: 18.0
),
),
),
//gets available employees and datetimes from the server
FutureBuilder(builder: (context,snapshot){
if (snapshot.data != null) {
List<Data> dataList = snapshot.data;
return Expanded(
child: ListView.builder(
itemBuilder: (_, position) {
return Card(
child: ListTile(
title: Text(dataList[position].dateTime),
subtitle: Text(dataList[position].employee),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(icon: Icon(Icons.edit), onPressed: () {
//Show dialog box to update item
showUpdateDialog(dataList[position]);
}),
IconButton(icon: Icon(Icons.check_circle, color: Colors.green,), onPressed: () {
}),
//Show dialog box to delete item
IconButton(icon: Icon(Icons.delete), onPressed: () {
deleteData(dataList[position].objectId);
}),
],
),
),
);
},
itemCount: dataList.length,
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
future: getDataList(),
),
Divider(
color: Colors.black,
),
scheduleTile()
],
);
}
void invokeDatePicker(){
DatePicker.showDateTimePicker(context,
showTitleActions: true,
minTime: DateTime(2020, 1, 1),
maxTime: DateTime(2021, 12, 31),
onChanged: (date) {
print('change $date');
},
onConfirm: (date) {
print('confirm $date');
_listTiles.add(DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString());
_titleTile = DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString();
setState(() {
});
},
currentTime: DateTime.now(),
locale: LocaleType.pt);
}
void showUpdateDialog(Data data) {
_nameController.text = data.employee;
showDialog(context: context,
builder: (_) => AlertDialog(
content: Container(
width: double.maxFinite,
child: TextField(
controller: _nameController,
decoration: InputDecoration(
labelText: "Atualizar funcionário disponível",
),
),
),
actions: <Widget>[
FlatButton(onPressed: () {
Navigator.pop(context);
data.employee = _nameController.text;
updateData(data);
}, child: Text("Atualizar")),
FlatButton(onPressed: () {
Navigator.pop(context);
}, child: Text("Cancelar")),
],
)
);
}
Widget scheduleTile(){
return Padding(
padding: EdgeInsets.only(bottom: 80.0),
child: Card(
color: Colors.grey,
child: ListTile(
title: Text(_titleTile),
subtitle: Text(_tileSubtitle),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: Icon(
Icons.edit,
color: standardIconColor,
size: 20.0,
),
onPressed: () {
setState(() {
employeeAvailable();
});
},
),
IconButton(
icon: Icon(
Icons.check_circle_outline,
color: _iconColor,
size: 20.0,
),
onPressed: () {
setState(() {
(_titleTile != standardTileTitle) ? confirmSchedule() : fillTimeDialog();
});
},
)
],
),
),
),
);
}
void fillTimeDialog(){
showDialog(context: context,
builder: (_) => AlertDialog(
content: Container(
width: double.maxFinite,
child: Text("Insira o horário disponível!"),
),
actions: <Widget>[
FlatButton(onPressed: () {
Navigator.pop(context);
}, child: Text("OK")),
],
)
);
}
void employeeAvailable(){
showDialog(context: context,
builder: (_) => AlertDialog(
content: Container(
width: double.maxFinite,
child: TextField(
controller: _nameController,
decoration: InputDecoration(
labelText: "Funcionário",
),
),
),
actions: <Widget>[
FlatButton(onPressed: () {
Navigator.pop(context);
//addTodo();
setState(() {
_tileSubtitle = "Disponível: " + _nameController.text;
});
}, child: Text("Inserir")),
FlatButton(onPressed: () {
Navigator.pop(context);
setState(() {
_tileSubtitle = " ";
});
}, child: Text("Desfazer")),
],
)
);
}
void confirmSchedule(){
showDialog(context: context,
builder: (_) => AlertDialog(
content: Container(
width: double.maxFinite,
child: Text("Confirma disponibilidade?")
),
actions: <Widget>[
FlatButton(onPressed: () {
Navigator.pop(context);
//addTodo();
addData();
setState(() {
_iconColor = alternateIconColor;
_tileSubtitle = "Disponível: " + _nameController.text;
});
}, child: Text("Confirma")),
FlatButton(onPressed: () {
Navigator.pop(context);
setState(() {
_iconColor = standardIconColor;
_tileSubtitle = " ";
});
}, child: Text("Não")),
],
)
);
}
void addData() {
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Row(
children: <Widget>[
Text("Adicionando informações..."),
CircularProgressIndicator(),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
duration: Duration(minutes: 1),
));
Data data = Data(employee: _tileSubtitle, dateTime: _titleTile);
DataUtils.addData(data)
.then((res) {
_scaffoldKey.currentState.hideCurrentSnackBar();
Response response = res;
if (response.statusCode == 201) {
//Successful
_nameController.text = "";
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Informações disponibilizadas!"), duration: Duration(seconds: 1),));
setState(() {
//Update UI
});
}
});
}
void deleteData(String objectId) {
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Excluindo disponibilidade..."),
CircularProgressIndicator(),
],
),
duration: Duration(minutes: 1),
),);
DataUtils.deleteData(objectId)
.then((res) {
_scaffoldKey.currentState.hideCurrentSnackBar();
Response response = res;
if (response.statusCode == 200) {
//Successfully Deleted
_scaffoldKey.currentState.showSnackBar(SnackBar(content: (Text("Disponibilidade excluída!")),duration: Duration(seconds: 1),));
setState(() {
});
} else {
//Handle error
}
});
}
void updateData(Data data) {
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Atualizando disponibilidade..."),
CircularProgressIndicator(),
],
),
duration: Duration(minutes: 1),
),);
DataUtils.updateData(data)
.then((res) {
_scaffoldKey.currentState.hideCurrentSnackBar();
Response response = res;
if (response.statusCode == 200) {
//Successfully Deleted
_nameController.text = "";
_scaffoldKey.currentState.showSnackBar(SnackBar(content: (Text("Disponibilidade atualizada!"))));
setState(() {
});
} else {
//Handle error
}
});
}
Future <List<Data>> getDataList() async{
List<Data> dataList = [];
Response response = await DataUtils.getDataList();
print("Code is ${response.statusCode}");
print("Response is ${response.body}");
if (response.statusCode == 200) {
var body = json.decode(response.body);
var results = body["results"];
for (var data in results) {
dataList.add(Data.fromJson(data));
}
} else {
//Handle error
}
return dataList;
}
}
data_utils.dart:
import 'dart:convert';
import 'package:http/http.dart';
import 'package:marca_horario/model/data.dart';
import 'package:marca_horario/constants.dart';
class DataUtils {
//static final String _baseUrl = "https://parseapi.back4app.com/classes/";
static final String _baseUrl = baseUrl;
//CREATE
static Future<Response> addData(Data data) async {
String apiUrl = _baseUrl + "Data";
Response response = await post(apiUrl,
headers: {
'X-Parse-Application-Id': kParseApplicationId,
'X-Parse-REST-API-Key': kParseRestApiKey,
'Content-Type': 'application/json'
},
body: json.encode(data.toJson()),
);
return response;
}
//READ
static Future getDataList() async{
String apiUrl = _baseUrl + "Data";
Response response = await get(apiUrl, headers: {
'X-Parse-Application-Id' : kParseApplicationId,
'X-Parse-REST-API-Key' : kParseRestApiKey,
});
return response;
}
//UPDATE
static Future updateData(Data data) async{
String apiUrl = _baseUrl + "Data/${data.objectId}";
Response response = await put(apiUrl, headers: {
'X-Parse-Application-Id' : kParseApplicationId,
'X-Parse-REST-API-Key' : kParseRestApiKey,
'Content-Type' : 'application/json',
},
body: json.encode(data.toJson())
);
return response;
}
//DELETE
static Future deleteData(String objectId) async{
String apiUrl = _baseUrl + "Data/$objectId";
Response response = await delete(apiUrl, headers: {
'X-Parse-Application-Id' : kParseApplicationId,
'X-Parse-REST-API-Key' : kParseRestApiKey,
});
return response;
}
}
Problem solved!
My problem was:import 'package:parse_server_sdk/parse_server_sdk.dart';
It needs to be replaced by:import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
and in pubspec.yaml it's necessary to use only the correspondent dependency:
parse_server_sdk_flutter: ^2.0.1
I want to perform post from client to server.
On the client side I'm using flutter and on the server side using nodejs. The problem is that I'm not able to perform post action. But if hardcode the route with the parameter value, I'm able to send data to server.
static String urlLogin = API.url +
'/authentication/api/login/ADMIN/12345';
but when I'm using below code and used body properties,not able to send data to server.
static String urlLogin = API.url +
'/authentication/api/login/';
my guest is there a problem with the parameter..maybe...I don't know what mistake that i have make.Hope can help me solve this problem.Thank you in advance.
ERROR
<pre>Cannot POST /authentication/api/login</pre>
</body>
</html>
FormatException: Unexpected character (at character 1)
(CLIENT SITE)
LoginPageForm.dart
class LoginPageForm extends StatefulWidget {
LoginPageForm({Key key}) : super(key: key);
#override
_LoginPageFormState createState() => _LoginPageFormState();
}
class _LoginPageFormState extends State<LoginPageForm> {
TextEditingController _idController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
child: TextFormField(
cursorColor: Colors.white,
style: TextStyle(color: Colors.white),
controller: _idController,
decoration: InputDecoration(
labelText: "No ID",
labelStyle: TextStyle(color: Colors.white),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white))),
validator: (value) {
if (value.isEmpty) {
return "Sila masukkan no id pengguna";
}
return null;
},
),
),
Container(
width: MediaQuery.of(context).size.width,
child: TextFormField(
cursorColor: Colors.white,
style: TextStyle(color: Colors.white),
controller: _passwordController,
decoration: InputDecoration(
labelText: "Kata Laluan",
labelStyle: TextStyle(color: Colors.white),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white))),
validator: (value) {
if (value.isEmpty) {
return "Sila masukkan kata laluan..";
}
return null;
},
),
),
RaisedButton.icon(
onPressed: () {
var login = new LoginPost(
userNo: _idController.text,
password: _passwordController.text);
//perform post
LoginRepository.login(login.toMap()).then((response) {
print(response);
});
},
icon: Icon(Icons.keyboard_arrow_right),
label: Text("Daftar Masuk")),
],
),
);
}
}
loginRepository.dart
class LoginRepository {
static String urlLogin = API.url + '/authentication/api/login/';
//static String urlLogin = API.url + '/authentication/api/login/ADMIN/12345';
static Future<LoginResponse> login(Map<String, dynamic> loginPost) async {
try {
final response =
await http.post(Uri.encodeFull(urlLogin), body: loginPost);
print(response.statusCode);
// if (response.statusCode == 200) {
print(response.body.toString());
return LoginResponse.fromMap(json.decode(response.body));
// } else {
// return null;
// }
} catch (e) {
print(e);
return null;
}
}
}
(SERVER SITE)
router.post('/api/login/:userNo/:password',(req,res)=>{
var userNo = req.params.userNo;
var password = req.params.password;
let Status;
const formData = {
userNo: userNo,
password : password
}
});
Posting with body doesn't give you a URL path, example where id = 1:
Post with URL: await http.post('user/' + id);
https://user/1
Post with Body: await http.post('user/', body:{'id': id});
https://user?id=1
So you should specify which one are you using in the server-side before doing the request with flutter. 😄
I am trying to download files from nodejs server. But when I implement onTap method on the gridview, it automatically runs the onTap function on start and every file starts downloading. I cannot figure out what am I doing wrong.Here is a preview of my code. I have implemented streambuilder to fetch the data.
GridView.builder(
padding: EdgeInsets.all(10),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 0.9),
itemCount: snapshot.data.data.length,
itemBuilder: (context, i) {
return Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.blue.withOpacity(0.3)),
child: Column(
children: <Widget>[
Container(
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: AssetImage('assets/pdf_icon.png'))),
),
Divider(),
for (var items in snapshot.data.data[i].attachments)
ResourceDetail(
name: snapshot.data.data[i].title,
author: snapshot.data.data[i].user.name,
onTap: downloadFile(
'url/api/${items.source}',
snapshot.data.data[i].title,
items.extension),
),
],
),
);
},
);
Here is download file method.
Future<void> downloadFile(
String url, String fileName, String extension) async {
var dio = new Dio();
var dir = await getExternalStorageDirectory();
var downloadDir =
await new io.Directory('${dir.path}/downloads').create(recursive: true);
io.File('${downloadDir.path}/$fileName.$extension').exists().then((a) async {
print(a);
if (a) {
print("Opening file");
showDialog(
context: context,
builder: (_) {
return AlertDialog(
backgroundColor: Color(0xff5b8c85),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
title: Text('File is already downloaded'),
actions: <Widget>[
FlatButton(
child: Text(
'Open',
style: TextStyle(color: Colors.white),
),
onPressed: () {
OpenFile.open('${downloadDir.path}/$fileName.$extension');
Navigator.pop(context);
})
],
);
});
return;
} else {
print("Downloading file");
openDialog();
await dio.download(url, '${downloadDir.path}/$fileName.$extension',
onReceiveProgress: (rec, total) {
if (mounted) {
setState(() {
progressValue = (rec / total);
progressString = ((rec / total) * 100).toStringAsFixed(0) + "%";
myDialogState.setState(() {
myDialogState.progressData = progressString;
myDialogState.progressValue = progressValue;
});
});
}
});
if (mounted) {
setState(() {
print('${downloadDir.path}');
});
}
print("Download completed");
}
});
}
The ResourceDetails in your GridView.builder, try replacing the onTap to this
onTap: ()=>downloadFile(
'url/api/${items.source}',
snapshot.data.data[i].title,
items.extension)
i was trying to do image upload with dart/flutter with aws s3 bucket with presigned url via nodejs. i successfully generated the presigned url and send it back to front end but cant not make the put request over s3 with the file.if i am printing the statuscode i am getting a 400.
import 'dart:io';
import 'dart:convert';
import 'package:path/path.dart';
import 'package:async/async.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
import '../global.dart';
class AddAccount extends StatelessWidget {
Widget build(context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(
color: Colors.grey
),
title: Text('Add Account', style: TextStyle(color: Colors.black54, fontSize: 20.0)),
backgroundColor: Colors.white,
),
body: addAccountBody(context),
);
}
Widget addAccountBody(context){
return ListView(
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: 'email'
),
textCapitalization: TextCapitalization.characters,
),
TextField(
decoration: InputDecoration(
labelText: 'name'
),
textCapitalization: TextCapitalization.characters,
),
OutlineButton(
onPressed: (){
openImagePicker(context);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.camera_alt),
Text('add image')
],
),
)
],
);
}
void openImagePicker(BuildContext context){
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 80.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
onPressed: (){
getImage(context, ImageSource.camera);
},
icon: Icon(Icons.camera_alt),
),
SizedBox(width: 20.0,),
IconButton(
onPressed: () async {
File image = await getImage(context, ImageSource.gallery);
http.Response response = await http.get('$url1/api/upload', headers: {
"x-auth" : 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YzQ0M2M0NDE0NjkxODM3ZTQxNTMxZTgiLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTQ3OTc1NzQ5fQ.73_tyhu3vTpsnMncmjTS0xDBec08pScxpa35yRlLuzQ'
});
Map<String, dynamic> uploadUrl = json.decode(response.body);
final dataType = lookupMimeType(image.path).split("/");
final imageUploadRequest = http.MultipartRequest("PUT", Uri.parse(uploadUrl['url']));
final file = await http.MultipartFile.fromPath("${uploadUrl['key']}", image.path, contentType: MediaType(dataType[0], dataType[1]));
imageUploadRequest.files.add(file);
imageUploadRequest.fields['user'] = Uri.encodeComponent('user');
imageUploadRequest.headers['Content-Type'] = 'image/jpeg';
print(file.contentType);
try{
final streamedResponse = await imageUploadRequest.send();
final res = await http.Response.fromStream(streamedResponse);
print(res.statusCode);
}catch(e){
print(e);
}
},
icon: Icon(Icons.camera),
),
],
),
);
}
);
}
Future<File> getImage(BuildContext context, ImageSource sourse) async {
File file = await ImagePicker.pickImage(source: sourse, maxWidth: 400.0);
Navigator.pop(context);
return file;
}
}
flutter code
const AWS = require('aws-sdk');
const uuid = require('uuid/v1');
const keys = require('../config/keys');
const { authenticate } = require('../middleware/authenticate')
const s3 = new AWS.S3({
accessKeyId: keys.accessKeyId,
secretAccessKey: keys.secretAccessKey
});
module.exports = (app) => {
app.get('/api/upload', authenticate, (req,res) => {
console.log(req.user.id);
const key = `${req.user.id}/${uuid()}.jpeg`;
s3.getSignedUrl('putObject', {
Bucket: 'flutter-bucket',
ContentType: 'image/jpeg',
Key: key
}, (err, url) => {
res.send({key, url});
})
});
}
node code
S3 Presigned URLs require raw bytes as the body, not multipart files. Thus, I used the following code:
List<int> content = await file.readAsBytes();
var streamed = http.StreamedRequest("PUT", Uri.parse(url));
streamed.headers["Content-Type"] = mimeType;
streamed.headers["Content-Length"] = "${content.length}";
streamed.sink.add(content);
streamed.sink.close();
var response = await streamed.send();