Search code examples
flutterdartfile-upload

Flutter - How to upload files to API?


I am trying to post files (html files since working on web) to the API. I am getting an error saying Null is not a subtype of type InstanceRef in type cast.
I don't know what is causing this. Everything seems to be fine to me in the code.

Here is the code:

          uploadFiles() async {
            ///
            try {
              var token =
                  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIyIiwibmJmIjoxNjc5MzgzMTY5LCJleHAiOjE2NzkzODQ5NjksImlhdCI6MTY3OTM4MzE2OX0.HL5Y39p0cxpbuOhbls-hjq2Nu_xnVGAJ4qacESp1yNw';
              var url =
                  Uri.parse("my_url");
              var request = http.MultipartRequest('POST', url);
              Map<String, String> headers = {
                "Authorization": "Bearer $token",
                "Content-type": "multipart/form-data"
              };
              request.headers.addAll(headers);

              request.fields
                  .addAll({"facility_id": "46", "module_id": "3263", "id": "1"});

              for (var file in files) {
                var reader = html.FileReader();
                reader.readAsArrayBuffer(file);

                var completer = Completer<List<int>>();
                bool _isCompleted = false; // add this flag

                reader.onLoadEnd.listen((event) {
                  if (!_isCompleted) {
                    // check if already completed
                    _isCompleted = true;
                    completer.complete(reader.result as List<int>);
                  }
                });
                var filename = file.name;
                var multipartFile = http.MultipartFile.fromBytes(
                  'file',
                  (await completer.future),
                  filename: filename,
                );
                request.files.add(multipartFile);
              }

              var response = await request.send();

              if (response.statusCode == 200) {
                print('Upload successful');
              } else {
                print('Upload failed');
              }
            } //
            catch (e) {
              print(e);
            }
          }

Solution

  • This is what finally worked for me:

              ///
          Future<void> upload() async {
            for (var i = 0; i < files.length; i++) {
              final file = files[i];
              final completer = Completer<List<int>>();
              final reader = FileReader();
    
              reader.onLoad.listen((event) {
                final bytesData = reader.result as List<int>;
                completer.complete(bytesData);
              });
    
              reader.readAsArrayBuffer(file);
              final bytesData = await completer.future;
              final request = http.MultipartRequest("POST", Uri.parse(url));
              final headers = {
                "Authorization": "Bearer $token",
                "Content-Type": "multipart/form-data",
                "Content-Length": bytesData.length.toString(),
                "Accept": "*/*",
              };
              request.headers.addAll(headers);
              if (requestFields != null) {
                request.fields.addAll(requestFields!);
              }
              request.files.add(http.MultipartFile.fromBytes(
                'files',
                bytesData,
                filename: file.name,
              ));
              final response = await request.send();
              handleResponse(response);
            }
          }
    

    Turns out content-length was required.