Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Dio interceptor: DioError [DioErrorType.DEFAULT]: Bad state: Can‘t finalize a finalized MultipartFile

Tags:

flutter

dio

Hi i'm trying refreshtoken logic in Dio interceptor. it's working fine for json body params, but its throwing DioError [DioErrorType.DEFAULT]: Bad state: Can‘t finalize a finalized MultipartFile when i tried uploading images.

onError: (DioError error) async {
      // Do something with response error
      if (error.response?.statusCode == 401) {
        // _dio.interceptors.requestLock.lock();
        Response response;
        RequestOptions options = error.response.request;
        response = await _dio
            .post('/user/refresh', data: {"refreshToken": _refreshToken});
    if (response.statusCode == 200) {
      final userData = json.encode(
        {
          'token': response.data["accessToken"],
          'tokenType': _tokenType,
          'refreshToken': response.data["refreshToken"]
        },
      );
      prefs.setString('userData', userData);
      
        options.data = formData;
      }
      options.headers["Authorization"] =
          "$_tokenType ${response.data['accessToken']}";
      return await _dio.request(options.path, options: options);
    } else {
      throw error;
    }
like image 713
Jones Stephen Avatar asked Nov 18 '25 10:11

Jones Stephen


1 Answers

I put together a workaround for this issue which basically consists of rebuilding the FormData before retrying. It feels a bit hacky but it works. I start by passing any info I need for the reconstruction in via the "extra" map in the request options so the interceptor has access to it. Here is some pseudo code:

//original request
dioResponse = await dio.post(
  'http://my/api/endpoint',
  data: myOriginalFormData,
  options: Options(
    headers: myHeaders,
    extra: {'pathToMyFile': pathToMyFile},
  ),
);

//and in my interceptor I use it to construct a fresh FormData that has not been finalized
final FormData newFormData = FormData.fromMap({
  'file': await MultipartFile.fromFile(
       requestOptions.extra['pathToMyFile'],
       contentType: MediaType('application/json', 'json')),
});

//retry with the fresh FormData
return dio.request(
  requestOptions.path,
  data: newFormData,
  options: requestOptions,
  cancelToken: requestOptions.cancelToken,
  onReceiveProgress: requestOptions.onReceiveProgress,
  onSendProgress: requestOptions.onSendProgress,
  queryParameters: requestOptions.queryParameters,
);

Anyone have thoughts on this approach? Any major downsides?

like image 146
rkunboxed Avatar answered Nov 21 '25 08:11

rkunboxed



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!