我试图从使用Laravel框架开发的后端获取数据。每个传递API中间件的请求都需要使用POST
请求。
当我使用不带标题的GET
请求时,将来的构建器可以正常工作,并且在后端数据更改后立即得到更新,但是由于没有提供令牌,我无法让Laravel抓住当前经过身份验证的用户。
但是当我使用带有标题的POST
请求或GET
请求时,它停止更新,我需要切换到另一页并返回以获取更改。
请在下面查看我的脚本:
Future<List<Document>> fetchDocuments(http.Client http, String token) async {
final headers = {'Authorization': 'Bearer $token'};
final response = await http.post(
'http://192.168.1.2:8000/api/documents/all',
headers: headers,
);
// Use the compute function to run parseDocuments in a separate isolate.
return compute(parseDocuments, response.body);
}
// A function that converts a response body into a List<DOcument>
List<Document> parseDocuments(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Document>((json) => Document.fromJSON(json)).toList();
}
class Document {
final int id;
final String name;
Document({this.id, this.name});
factory Document.fromJSON(Map<String, dynamic> json) {
return Document(
id: json['id'] as int,
name: json['name'] as String,
);
}
}
class StudentDocumentScreen extends StatefulWidget {
StudentDocumentScreen({Key key}) : super(key: key);
_StudentDocumentScreenState createState() => _StudentDocumentScreenState();
}
class _StudentDocumentScreenState extends State<StudentDocumentScreen> {
final storage = FlutterSecureStorage();
final _uploadURL = 'http://192.168.1.2:8000/api/documents';
final _scaffoldKey = GlobalKey<ScaffoldState>();
final SnackBar uploadingSnackbar = SnackBar(
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Uploading file, this may take a while...',
style: TextStyle(color: Colors.white),
),
),
);
final SnackBar successSnackbar = SnackBar(
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'File uploaded!',
style: TextStyle(color: Colors.white),
),
),
backgroundColor: Colors.green,
);
final SnackBar errorSnackbar = SnackBar(
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Oops... Something went wrong!',
style: TextStyle(color: Colors.white),
),
),
backgroundColor: Colors.red,
);
String _token;
String _path;
@override
void initState() {
super.initState();
_getToken();
}
void _getToken() async {
String token = await storage.read(key: 'accessToken');
setState(() => _token = token);
}
void _openFileExplorer() async {
try {
_path = null;
_path = await FilePicker.getFilePath();
} on PlatformException catch (e) {
print('Unsupported operation');
print(e);
}
if (!mounted) return;
if (_path != null || _path.isNotEmpty) {
_uploadDocument(_path);
}
}
void _uploadDocument(String path) async {
_scaffoldKey.currentState.showSnackBar(uploadingSnackbar);
try {
var multipartFile = await http.MultipartFile.fromPath('document', path);
var request = http.MultipartRequest('POST', Uri.parse(_uploadURL));
request.headers.addAll({'Authorization': 'Bearer $_token'});
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
_scaffoldKey.currentState.showSnackBar(successSnackbar);
} else {
_scaffoldKey.currentState.showSnackBar(errorSnackbar);
}
} catch (e) {
print('Error when uploading files');
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text('Koleksi Dokumen'),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _openFileExplorer,
),
);
}
Widget _buildBody() {
return FutureBuilder<List<Document>>(
future: fetchDocuments(http.Client(), _token),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? DocumentList(documents: snapshot.data)
: Center(child: CircularProgressIndicator());
},
);
}
}
class DocumentList extends StatelessWidget {
final List<Document> documents;
const DocumentList({Key key, this.documents}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: documents.length,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Icon(
Icons.insert_drive_file,
color: Colors.black12,
size: 50.0,
),
),
Text(
documents[index].name,
textAlign: TextAlign.center,
),
],
),
),
);
},
);
}
}
下面是laravel脚本:
# in the `api.php`
Route::post('documents/all', 'DocumentController@index');
# in the `DocumentController`
public function index()
{
$userId = auth()->user()->id;
return Document::whereUserId($userId)
->get()
->load('user');
}
有什么主意吗?预先感谢。
答案 0 :(得分:0)
我刚刚找到了一个临时解决方案,在上传进度后放置setState(() {});
即可完成工作。
如果你们有更好的一个,请随时回答。
解决方案:
void _uploadDocument(String path) async {
_scaffoldKey.currentState.showSnackBar(uploadingSnackbar);
try {
var multipartFile = await http.MultipartFile.fromPath('document', path);
var request = http.MultipartRequest('POST', Uri.parse(_uploadURL));
request.headers.addAll({'Authorization': 'Bearer $_token'});
request.files.add(multipartFile);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
_scaffoldKey.currentState.showSnackBar(successSnackbar);
setState(() {}); // reload state
} else {
_scaffoldKey.currentState.showSnackBar(errorSnackbar);
}
} catch (e) {
print('Error when uploading files');
print(e);
}
}