skip to Main Content

Am trying to upload an image to server, but when its making the request its calls the interceptor to refreshToken after getting the token it will throw this error:

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DioException [unknown]: null
E/flutter ( 5915): Error: Bad state: The FormData has already been finalized. This typically means you are using the same FormData in repeated requests.

Here is the code:

final token = storageService.getAccessToken();
String fileName = photo.path.split('/').last;
Map<String, String> headers = <String, String>{
  'Accept': 'application/json',
  'content-type': 'multipart/form-data',
  'Authorization': token!,
};

final formData = dios.FormData.fromMap({
  "image": await dios.MultipartFile.fromFile(
    photo.path,
    filename: fileName,
  ),
});
final response = await dio.patch(
  "${AppConfig.endPoint}api/upload-picture",
  data: formData,
  options: dios.Options(
    headers: headers,
  ),
);

if (response.statusCode == 200) {
  return true;
} else if (response.data['code'] == 'token_not_valid') {
  final anotherformData = dios.FormData.fromMap({
    "profile_picture": await dios.MultipartFile.fromFile(
      photo.path,
      filename: fileName,
    ),
  });
  await dio.patch(
    "${AppConfig.endPoint}api/upload-picture",
    data: anotherformData,
    options: dios.Options(
      headers: headers,
    ),
  );
} else {
  throw Exception(response.statusMessage);
}
getUserProfile();
return true;}

The InterceptorsWrapper

dio.interceptors.addAll([
  PrettyDioLogger(
      requestHeader: true,
      requestBody: true,
      responseBody: true,
      responseHeader: false,
      error: true,
      compact: true,
      request: true,
      maxWidth: 150),

  dios.InterceptorsWrapper(
    onError: (dios.DioException e, handler) async {
      if (e.response?.data['code'] == 'token_not_valid') {
        // If a 401 response is received, refresh the access token
        RefreshTokenResponse? newAccessToken = await refreshToken(
            RefreshTokenBody(
                refresh: storageService.getRefreshToken() ?? ''));

        //Save the  new token and refresh token here
        storageService.setAccessToken(newAccessToken?.access ?? '');

        // Update the request header with the new access token
        e.requestOptions.headers['Authorization'] =
            'Bearer ${newAccessToken?.access}';

        // Repeat the request with the updated header
        return handler.resolve(await dio.fetch(e.requestOptions));
      }
      return handler.next(e);
    },
  ),
]);

Any Idea on how i fix this issue please. Thank you.

enter image description here

2

Answers


  1. Chosen as BEST ANSWER

    I was able to fix the issue, what i did was to make sure i do a check if the token has expired or not before making the request to upload the photo, with the help of this package jwt_decode: https://pub.dev/packages/jwt_decode


  2. You attempt to reuse the same FormData object for multiple requests. FormData objects in Dio are designed to be used for a single HTTP request, and they cannot be modified or reused after finalization.

    You should create a new FormData object for each HTTP request. In your code, you’re trying to reuse the same FormData object formData for the initial request and anotherformData for the subsequent request, which is causing the error.

    final token = storageService.getAccessToken();
        String fileName = photo.path.split('/').last;
        Map<String, String> headers = <String, String>{
          'Accept': 'application/json',
          'content-type': 'multipart/form-data',
          'Authorization': token!,
        };
        
        final formData = dios.FormData.fromMap({
          "image": await dios.MultipartFile.fromFile(
            photo.path,
            filename: fileName,
          ),
        });
        final response = await dio.patch(
          "${AppConfig.endPoint}api/upload-picture",
          data: formData,
          options: dios.Options(
            headers: headers,
          ),
        );
        
        if (response.statusCode == 200) {
          return true;
        } else if (response.data['code'] == 'token_not_valid') {
          final anotherFormData = dios.FormData.fromMap({
            "profile_picture": await dios.MultipartFile.fromFile(
              photo.path,
              filename: fileName,
            ),
          });
          await dio.patch(
            "${AppConfig.endPoint}api/upload-picture",
            data: anotherFormData,
            options: dios.Options(
              headers: headers,
            ),
          );
        } else {
          throw Exception(response.statusMessage);
        }
        getUserProfile();
        return true;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search