Search code examples
flutterpostmultipartform-datafilepicker.io

Flutter error: Expected a value of type 'File', but got one of type 'FilePickerResult'


I am trying to send some data and a file to my node js server. The file is a .txt file and I am using FilePicker to get the file and MultiPartRequest to send it.

This is the Widget with the text forms and the attachment button:

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Crear una nueva tarea'),
        backgroundColor: Colors.green[300],
      ),
      body: ChangeNotifierProvider<LoginFormProvider>(
          create: (context) => LoginFormProvider(),
          child: Consumer<LoginFormProvider>(builder: (context, value, child) {
            final loginFormProvider =
                Provider.of<LoginFormProvider>(context, listen: true);
            return Container(
                color: Colors.grey[100],
                padding: EdgeInsets.symmetric(horizontal: 20),
                child: Center(
                  child: ConstrainedBox(
                    constraints: BoxConstraints(maxHeight: 370),
                    child: Form(
                      key: loginFormProvider.formKey,
                      child: Column(
                        children: [
                          TextFormField(
                            onChanged: (value) =>
                                loginFormProvider.title = value,
                            decoration: buildInputDecoration(
                                hint: 'Enunciado',
                                label: 'Enunciado de la tarea',
                                icon: Icons.title),
                          ),
                          SizedBox(
                            height: 20,
                          ),
                          TextFormField(
                            onChanged: (value) =>
                                loginFormProvider.date = value,
                            cursorColor: Colors.green,
                            decoration: buildInputDecoration(
                                hint: 'Fecha limite',
                                label: 'Fecha limite de entrega',
                                icon: Icons.date_range),
                          ),
                          SizedBox(
                            height: 20,
                          ),
                          ElevatedButton(
                              onPressed: () async {
                                final result =
                                    await FilePicker.platform.pickFiles(
                                  type: FileType.custom,
                                  allowedExtensions: ['txt', 'docx'],
                                );
                                final file = result!.files.first.name;
                                value.setFile(result);
                              },
                              child: Text('Seleccionar archivo')),
                          SizedBox(
                            height: 20,
                          ),
                          CustomOutlinedButton(
                              onPressed: () async {
                                if (value.file == null) return;
                                value.makePostRequest(loginFormProvider.title,
                                    id, teacherID, loginFormProvider.date);
                                
                                Navigator.pop(context);
                              },
                              text: 'Crear Tarea'),
                        ],
                      ),
                    ),
                  ),
                ));
          })),
    );
  }

And I am trying to send the request as follows in this class:

class LoginFormProvider extends ChangeNotifier {
  GlobalKey<FormState> formKey = new GlobalKey<FormState>();

  var file;
  String role = '';
  String id = '';
  String lastname = '';
  String firstname = '';
  String password = '';
  String tid = '';
  String name = '';
  String title = '';
  int teacherid = 0;
  int subjectid = 0;
  String date = '';

  bool validateForm() {
    if (formKey.currentState!.validate()) {
      return true;
    } else {
      return false;
    }
  }

  Future setFile(txt) async {
    this.file = txt;
    this.notifyListeners();
  }

  Future makePostRequest(
      String title, int subjectid, int teacherid, String limitDate) async {
    var url = Uri.parse('http://localhost:8000/newHomework');
    var request = http.MultipartRequest('POST', url);
    var headers = {'Content-Type': 'text/plain; charset=UTF-8'};
    File fileByte = this.file;
    Uint8List data = await fileByte.readAsBytes();
    List<int> list = data.cast();
    request.files
        .add(http.MultipartFile.fromBytes('text', list, filename: 'tarea1'));
    request.headers.addAll(headers);
    request.fields['title'] = title;
    request.fields['limitDate'] = limitDate;
    request.fields['subjectid'] = subjectid.toString();
    request.fields['teacherid'] = teacherid.toString();
    request.fields['ext'] = '.txt';

    var res = await request.send();
    return res.stream.bytesToString().asStream().listen((event) {
      var parsedJson = json.decode(event);
      print(parsedJson);
    });
  }
}

And I am getting Expected a value of type 'File', but got one of type 'FilePickerResult'

I do not know how to fix this to send the file... Any ideas on how to go through this?


Solution

  • What you are doing wrong is You are setting FilePickerResult instead of File. [Edited using a different approach for the web.

    ElevatedButton(
                                  onPressed: () async {
                                    final result =
                                        await FilePicker.platform.pickFiles(
                                      type: FileType.custom,
                                      allowedExtensions: ['txt', 'docx'],
     withReadStream:
              true,
    
                                    );
    //Edited Part 
                          var file = result!.files.single;                              
                                    value.setFile(file);
                                  },
                                  child: Text('Seleccionar archivo'))
    

    and also

     PlatformFile file = null;
    
     Future setFile(PlatformFile txt) async {
        this.file = txt;
        this.notifyListeners();
      }
    
     Future makePostRequest(
          String title, int subjectid, int teacherid, String limitDate) async {
        var url = Uri.parse('http://localhost:8000/newHomework');
        var request = http.MultipartRequest('POST', url);
        var headers = {'Content-Type': 'text/plain; charset=UTF-8'};
        
    
        request.files.add(new http.MultipartFile(
            "text", file.readStream, file.size,
            filename: "tarea1"));
    
    
        request.headers.addAll(headers);
        request.fields['title'] = title;
        request.fields['limitDate'] = limitDate;
        request.fields['subjectid'] = subjectid.toString();
        request.fields['teacherid'] = teacherid.toString();
        request.fields['ext'] = '.txt';
    
        var res = await request.send();
        return res.stream.bytesToString().asStream().listen((event) {
          var parsedJson = json.decode(event);
          print(parsedJson);
        });
      }