FlutterDio拦截器:DioError [默认DioError类型]:错误状态:无法完成已完成的MultipartFile

vecaoik1  于 2023-03-13  发布在  Flutter
关注(0)|答案(2)|浏览(466)

嗨,我正在尝试刷新标记逻辑在Dio拦截器。它的工作正常的json体参数,但它抛出DioError [DioErrorType.DEFAULT]:错误状态:尝试上载图像时无法完成已完成的MultipartFile

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;
    }
kmbjn2e3

kmbjn2e31#

我为这个问题制定了一个变通方案,基本上包括在重试之前重建FormData。这感觉有点笨拙,但很有效。我首先通过请求选项中的“extra”Map传递重建所需的任何信息,以便拦截器可以访问它。下面是一些伪代码:

//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,
);

有人对这种方法有什么想法吗?有什么主要的缺点吗?

dfddblmv

dfddblmv2#

似乎发送相同的表单数据而不完成最后一个请求的问题,通过以下方式解决了相同的问题:

static final Dio dio2 = Dio();

  static Future<dynamic> _retry(RequestOptions requestOptions) async {
    final options = new Options(
      method: requestOptions.method,
      headers: (await getHeaders()),
    );

    options.responseType = (ResponseType.json);
    Map<String, String>? data;
    try {
      data = Map.fromEntries(requestOptions.data?.fields);
    } catch (e) {}
    var res = dio2.request<dynamic>(
        requestOptions.baseUrl + requestOptions.path,
        data: data == null ? null : FormData.fromMap(data),
        queryParameters: requestOptions.queryParameters,
        options: options);

    return res;
  }

在你想重新发送相同请求的块中使用它:

handler.resolve(await _retry(response.requestOptions));

相关问题