Click here to Skip to main content
16,022,297 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am a beginner in flutter development, I want to call the API to update the user profile, in the API one of them consist of 'image' & 'proof' field,that field can be left blank, but the problem is whenever I left those fields empty and click the 'edit' button, I always receive this response from the server :
JSON
{
  "status": 500,
  "message": "The \"path\" argument must be of type string. Received an instance of Array"
}

my purpose is I want to empty 'image' & 'proof' fields if I not choose any image & background image, but if I choose it I want those field is fulfil with the image path


I hope there is someone that can help me to find the solution of this problem,

here is my code :

  1  // Auth Service
  2  class AuthService {
  3    static String? token;
  4    static String? bioDateId;
  5  
  6    final TokenManager tokenManager = TokenManager();
  7    final BiodateIdManager biodateIdManager = BiodateIdManager();
  8  // Update Bio
  9    Future<bool> updateBio({
 10      required String firstName,
 11      required String lastName,
 12      required String birthDate,
 13      required String gender,
 14      required String phone,
 15      required String address,
 16      required String province,
 17      required String regencies,
 18      required String institutionName,
 19      required String pupils,
 20      required String field,
 21      String? image,
 22      String? proof,
 23    }) async {
 24      String? token = await tokenManager.getToken();
 25      String? bioDateId = await biodateIdManager.getBiodateId();
 26      try {
 27        // Create a Map for form data
 28        Map<String, dynamic> formDataMap = {
 29          "firstName": firstName,
 30          "lastName": lastName,
 31          "birthDate": birthDate,
 32          "gender": gender,
 33          "phone": phone,
 34          "address": address,
 35          "province": province,
 36          "regencies": regencies,
 37          "institutionName": institutionName,
 38          "field": field,
 39          "pupils": pupils,
 40        };
 41  
 42        // Get MIME type for the files and add to formDataMap if not null
 43        if (proof != null && proof.isNotEmpty) {
 44          String? proofMimeType = lookupMimeType(proof);
 45          if (proofMimeType != null) {
 46            MultipartFile proofMultipartFile = await MultipartFile.fromFile(
 47              proof,
 48              filename: 'proof.png',
 49              contentType: MediaType.parse(proofMimeType),
 50            );
 51            formDataMap["proof"] = proofMultipartFile;
 52          } else {
 53            debugPrint('Invalid proof MIME type');
 54          }
 55        }
 56  
 57        if (image != null && image.isNotEmpty) {
 58          String? imageMimeType = lookupMimeType(image);
 59          if (imageMimeType != null) {
 60            MultipartFile imageMultipartFile = await MultipartFile.fromFile(
 61              image,
 62              filename: 'image.png',
 63              contentType: MediaType.parse(imageMimeType),
 64            );
 65            formDataMap["image"] = imageMultipartFile;
 66          } else {
 67            debugPrint('Invalid image MIME type');
 68          }
 69        }
 70  
 71        var response = await Dio().put(
 72          "http://192.168.1.5:3000/user/update-biodate?id=$bioDateId",
 73          data: FormData.fromMap(formDataMap),
 74          options: Options(
 75            headers: {
 76              "Content-Type": "multipart/form-data",
 77              "Authorization": "Bearer $token"
 78            },
 79          ),
 80        );
 81  
 82        if (response.statusCode == 200) {
 83          // Update successful
 84          return true;
 85        } else {
 86          throw Exception('Failed to Update Bio : ${response.data['message']}');
 87        }
 88      } on DioException catch (e) {
 89        if (e.response?.statusCode == 400) {
 90          debugPrint('Error 400: ${e.response?.data}');
 91          throw Exception('Update Bio failed: ${e.response?.data['message']}');
 92        } else {
 93          debugPrint('Error: ${e.toString()}');
 94          throw Exception('Failed to Update Bio');
 95        }
 96      }
 97    }
 98  }

  1  // UpdateUserController
  2  class UpdateUserController {
  3    final AuthService _authService = AuthService();
  4    UpdateUserModel updateUserModel = UpdateUserModel();
  5  
  6    TextEditingController firstNameController = TextEditingController();
  7    TextEditingController lastNameController = TextEditingController();
  8    TextEditingController birthDateController = TextEditingController();
  9    TextEditingController genderController = TextEditingController();
 10    TextEditingController phoneController = TextEditingController();
 11    TextEditingController addressController = TextEditingController();
 12    TextEditingController provinceController = TextEditingController();
 13    TextEditingController regenciesController = TextEditingController();
 14    TextEditingController institutionNameController = TextEditingController();
 15    TextEditingController studyFieldController = TextEditingController();
 16    TextEditingController uniqueIdController = TextEditingController();
 17    TextEditingController imageController = TextEditingController();
 18    TextEditingController proofController = TextEditingController();
 19  
 20    String? _selectedImagePath;
 21    String? _selectedProofPath;
 22  
 23    void setImagePath(String filePath) {
 24      _selectedImagePath = filePath;
 25      debugPrint('Selected image path set: $_selectedImagePath');
 26    }
 27  
 28    void setProofPath(String filePath) {
 29      _selectedProofPath = filePath;
 30      debugPrint('Selected proof path set: $_selectedProofPath');
 31    }
 32  
 33    void reset() {
 34      _selectedImagePath = null;
 35      _selectedProofPath = null;
 36      firstNameController.clear();
 37      lastNameController.clear();
 38      birthDateController.clear();
 39      genderController.clear();
 40      phoneController.clear();
 41      addressController.clear();
 42      provinceController.clear();
 43      regenciesController.clear();
 44      institutionNameController.clear();
 45      studyFieldController.clear();
 46      uniqueIdController.clear();
 47    }
 48  
 49    void dispose() {
 50      firstNameController.dispose();
 51      lastNameController.dispose();
 52      birthDateController.dispose();
 53      genderController.dispose();
 54      phoneController.dispose();
 55      addressController.dispose();
 56      provinceController.dispose();
 57      regenciesController.dispose();
 58      institutionNameController.dispose();
 59      studyFieldController.dispose();
 60      uniqueIdController.dispose();
 61    }
 62  
 63    bool fileExists(String path) {
 64      return File(path).existsSync();
 65    }
 66  
 67    Future<void> updateBio(BuildContext context) async {
 68      DialogHelper.showLoading(context);
 69  
 70      String firstName = firstNameController.text.trim();
 71      String lastName = lastNameController.text.trim();
 72      String birthDate = birthDateController.text.trim();
 73      String gender = genderController.text.trim();
 74      String phone = phoneController.text.trim();
 75      String address = addressController.text.trim();
 76      String province = provinceController.text.trim();
 77      String regencies = regenciesController.text.trim();
 78      String institutionName = institutionNameController.text.trim();
 79      String studyField = studyFieldController.text.trim();
 80      String uniqueId = uniqueIdController.text.trim();
 81      // String? image = imageController.text.trim();
 82      // String? proof = proofController.text.trim();
 83      String? image = _selectedImagePath;
 84      String? proof = _selectedProofPath;
 85  
 86      try {
 87        bool bioUpdated = await _authService.updateBio(
 88          firstName: firstName,
 89          lastName: lastName,
 90          birthDate: birthDate,
 91          gender: gender,
 92          phone: phone,
 93          address: address,
 94          province: province,
 95          regencies: regencies,
 96          institutionName: institutionName,
 97          field: studyField,
 98          pupils: uniqueId,
 99          image: image,
100          proof: proof,
101        );
102        DialogHelper.hideLoading(context);
103  
104        if (bioUpdated) {
105          reset();
106          Navigator.push(
107              context,
108              MaterialPageRoute(
109                  builder: (context) => const EduPassApp(
110                        initialPageIndex: 4,
111                      )));
112          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
113            content: Text('UpdateBio berhasil'),
114            duration: Duration(seconds: 1),
115          ));
116          debugPrint('UpdateBio berhasil');
117        } else {
118          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
119            content: Text('UpdateBio gagal'),
120            duration: Duration(seconds: 2),
121          ));
122          debugPrint('UpdateBio gagal');
123        }
124      } catch (e) {
125        DialogHelper.hideLoading(context);
126        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
127          content: Text('Error: $e'),
128          duration: const Duration(seconds: 2),
129        ));
130        debugPrint('Error saat UpdateBio: $e');
131      }
132    }
133  }

  1  // ProfileUserDetail
  2  class ProfileDetailUser extends StatefulWidget {
  3    const ProfileDetailUser({super.key});
  4  
  5    @override
  6    State<ProfileDetailUser> createState() => _ProfileDetailUserState();
  7  }
  8  
  9  class _ProfileDetailUserState extends State<ProfileDetailUser> {
 10    String? _selectedImagePath;
 11    String? _selectedBackgroundPath;
 12    final UpdateUserController updateController = UpdateUserController();
 13  
 14    void _handleImageSelected(String filePath) {
 15      setState(() {
 16        _selectedImagePath = filePath;
 17        updateController.setImagePath(filePath);
 18        // updateController.imageController.text = filePath;
 19      });
 20      debugPrint('File path: $filePath');
 21    }
 22  
 23    void _handleBackgroundSelected(String filePath) {
 24      setState(() {
 25        _selectedBackgroundPath = filePath;
 26        updateController.setProofPath(filePath);
 27        // updateController.proofController.text = filePath;
 28      });
 29      debugPrint('File path: $filePath');
 30    }
 31  
 32  
 33    @override
 34    Widget build(BuildContext context) {
 35      return ChangeNotifierProvider(
 36        create: (context) => ProfileUserController(),
 37        child: Consumer<ProfileUserController>(
 38          builder: (context, profileController, child) {
 39            if (profileController.isLoading) {
 40              return const Center(child: CircularProgressIndicator());
 41            }
 42  
 43            if (profileController.userData == null) {
 44              return ErrorScreen(onRetry: profileController.retryFetchUserData);
 45            }
 46  
 47            // Initialize UpdateUserController's text controllers with data from ProfileUserController
 48            updateController.firstNameController.text =
 49                profileController.userData!['biodate']['firstName'] ?? '';
 50            updateController.lastNameController.text =
 51                profileController.userData!['biodate']['lastName'] ?? '';
 52            String birthDate =
 53                profileController.userData!['biodate']['birthDate'] ?? '';
 54            if (birthDate.isNotEmpty) {
 55              updateController.birthDateController.text =
 56                  birthDate.substring(0, 10); // Format date
 57            }
 58  
 59            updateController.genderController.text =
 60                profileController.userData!['biodate']['gender'] ?? '';
 61            updateController.phoneController.text =
 62                profileController.userData!['biodate']['phone'] ?? '';
 63            updateController.addressController.text =
 64                profileController.userData!['biodate']['address'] ?? '';
 65            updateController.provinceController.text =
 66                profileController.userData!['biodate']['province'] ?? '';
 67            updateController.regenciesController.text =
 68                profileController.userData!['biodate']['regencies'] ?? '';
 69            updateController.institutionNameController.text =
 70                profileController.userData!['biodate']['institutionName'] ?? '';
 71            updateController.studyFieldController.text =
 72                profileController.userData!['biodate']['field'] ?? '';
 73            updateController.uniqueIdController.text =
 74                profileController.userData!['biodate']['pupils'] ?? '';
 75            // updateController.imageController.text =
 76            //     profileController.userData!['biodate']['image'];
 77            // updateController.proofController.text =
 78            //     profileController.userData!['biodate']['proof'];
 79            // updateController.setImagePath(
 80            //     profileController.userData!['biodate']['image'] ?? '');
 81            // updateController.setProofPath(
 82            //     profileController.userData!['biodate']['proof'] ?? '');
 83  
 84            return Scaffold(
 85              appBar: AppBar(
 86                backgroundColor: Colors.white,
 87                elevation: 0,
 88                leading: IconButton(
 89                  icon: const Icon(Icons.arrow_back, color: Colors.black),
 90                  onPressed: () {
 91                    Navigator.pushReplacement(
 92                      context,
 93                      MaterialPageRoute(
 94                        builder: (context) =>
 95                            const EduPassApp(initialPageIndex: 4),
 96                      ),
 97                    );
 98                  },
 99                ),
100                title: Text(
101                  'Profile',
102                  style: GoogleFonts.poppins(
103                    color: Colors.black,
104                    fontSize: 20,
105                    fontWeight: FontWeight.bold,
106                  ),
107                ),
108              ),
109              body: Container(
110                color: Colors.grey.shade100,
111                child: SingleChildScrollView(
112                  padding: const EdgeInsets.only(
113                      left: 16, right: 16, top: 16, bottom: 30),
114                  child: Column(
115                    children: [
116                      UserAvatarField(onFileSelected: _handleImageSelected),
117                      const SizedBox(height: 20),
118                      if (_selectedImagePath != null) ...[
119                        Text('Selected file: $_selectedImagePath'),
120                        // Jika Anda ingin menampilkan gambar yang diunggah
121                        Image.file(
122                          File(_selectedImagePath!),
123                          height: 200,
124                        ),
125                      ],
126                      const SizedBox(height: 16),
127                      ProfileTextField(
128                        label: 'Nama Depan',
129                        placeholder: 'John',
130                        controller: updateController.firstNameController,
131                      ),
132                      const SizedBox(height: 16),
133                      ProfileTextField(
134                        label: 'Nama Belakang',
135                        placeholder: 'Doe',
136                        controller: updateController.lastNameController,
137                      ),
138                      const SizedBox(height: 16),
139                      ProfileTextField(
140                        label: 'Email',
141                        placeholder: 'stevejobs@gmail.com',
142                        enabled: false,
143                        controller: TextEditingController(
144                          text: profileController.userData!['email'] ?? '',
145                        ),
146                      ),
147                      const SizedBox(height: 16),
148                      ProfileDateField(
149                        label: 'Select Date',
150                        placeholder: 'YYYY-MM-DD',
151                        controller: updateController.birthDateController,
152                      ),
153                      const SizedBox(height: 16),
154                      ElevatedButton(
155                        onPressed: () {
156                          debugPrint(
157                              'Selected Date: ${updateController.birthDateController.text}');
158                        },
159                        child: const Text('Print Selected Date'),
160                      ),
161                      const SizedBox(height: 16),
162                      DropdownField(
163                        label: 'Jenis Kelamin',
164                        items: const ['Pria', 'Wanita', ''],
165                        controller: updateController.genderController,
166                        onChanged: (value) {
167                          debugPrint(
168                              'Selected Gender: ${updateController.genderController.text}');
169                        },
170                      ),
171                      const SizedBox(height: 16),
172                      UploadImageField(onFileSelected: _handleBackgroundSelected),
173                      const SizedBox(height: 20),
174                      if (_selectedBackgroundPath != null) ...[
175                        Text('Selected file: $_selectedBackgroundPath'),
176                        // Jika Anda ingin menampilkan gambar yang diunggah
177                        Image.file(
178                          File(_selectedBackgroundPath!),
179                          height: 200,
180                        ),
181                      ],
182                      const SizedBox(height: 16),
183                      ProfileTextField(
184                        label: 'Provinsi',
185                        placeholder: 'California',
186                        controller: updateController.provinceController,
187                      ),
188                      const SizedBox(height: 16),
189                      ProfileTextField(
190                        label: 'Regencies',
191                        placeholder: 'San Francisco',
192                        controller: updateController.regenciesController,
193                      ),
194                      const SizedBox(height: 16),
195                      ProfileTextField(
196                        label: 'Nomor HP',
197                        placeholder: '08123456789',
198                        controller: updateController.phoneController,
199                      ),
200                      const SizedBox(height: 16),
201                      ProfileTextField(
202                        label: 'Alamat',
203                        placeholder: 'Jalan Jendral Sudirman No 1',
204                        controller: updateController.addressController,
205                      ),
206                      const SizedBox(height: 16),
207                      ProfileTextField(
208                        label: 'Nama Instansi',
209                        placeholder: 'Harvard University',
210                        controller: updateController.institutionNameController,
211                      ),
212                      const SizedBox(height: 16),
213                      ProfileTextField(
214                        label: 'Bidang Studi/Jurusan',
215                        placeholder: 'Teknik Informatika',
216                        controller: updateController.studyFieldController,
217                      ),
218                      const SizedBox(height: 16),
219                      ProfileTextField(
220                        label: 'NIM/NISN',
221                        placeholder: '123123123',
222                        controller: updateController.uniqueIdController,
223                      ),
224                      const SizedBox(height: 32),
225                      ElevatedButton(
226                        onPressed: () {
227                          updateController.updateBio(context);
228                          updateController.reset();
229  
230                          // String? image = _selectedImagePath;
231                          // String? proof = _selectedBackgroundPath;
232                          // updateController.updateBio(context, image, proof);
233                        },
234                        style: ElevatedButton.styleFrom(
235                          backgroundColor: Colors.indigo,
236                          padding: const EdgeInsets.symmetric(
237                              horizontal: 40, vertical: 16),
238                          shape: RoundedRectangleBorder(
239                            borderRadius: BorderRadius.circular(8),
240                          ),
241                        ),
242                        child: Text(
243                          'Edit',
244                          style: GoogleFonts.poppins(
245                            fontSize: 16,
246                            fontWeight: FontWeight.bold,
247                            color: Colors.white,
248                          ),
249                        ),
250                      ),
251                    ],
252                  ),
253                ),
254              ),
255            );
256          },
257        ),
258      );
259    }
260  }


What I have tried:

I have tried to delete the MIME image process but it's still not working
Posted
Updated 8-Jul-24 22:16pm
v2
Comments
wseng 23-Jul-24 0:27am    
Have you tried using an API testing tool like Postman? Try posting an empty value to see what output you get.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900