我可以在以后的构建器中使用POST请求吗?

时间:2019-09-15 01:22:40

标签: flutter

我试图从使用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');
}

有什么主意吗?预先感谢。

1 个答案:

答案 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);
    }
  }