Token过期后重发Multipart请求时遭遇异常问题
解决Multipart请求重试时的"Can't finalize a finalized MultipartFile"错误
问题根源
MultipartFile基于流式传输实现,首次发送请求时文件流已被完全消耗并关闭(finalized),重试时无法重复读取同一个流对象,因此触发该错误。
可行解决方案
方案1:每次重试时重新构建MultipartRequest
不要复用原有的MultipartRequest实例,将请求构建逻辑封装为可重复调用的方法,确保每次重试都生成全新的请求对象和文件流。
代码修改示例:
首先封装请求构建方法:
Future<http.MultipartRequest> buildMultipartRequest( String url, Map<String, String> headers, Map<String, String> fields, List<String>? filePaths, List<String>? fileKeys ) async { var request = http.MultipartRequest('POST', Uri.parse(url)); request.headers.addAll(headers); request.fields.addAll(fields); if (filePaths != null && fileKeys != null) { for (int i = 0; i < filePaths.length; i++) { // 每次调用fromPath都会重新打开文件流,避免复用已关闭的流 request.files.add(await http.MultipartFile.fromPath(fileKeys[i], filePaths[i])); } } return request; }
然后在重试逻辑中覆盖retryRequest方法,重新生成请求:
class ExpiredTokenRetryPolicy extends RetryPolicy { @override int get maxRetryAttempts => 1; // 保存构建请求所需的参数(需在初始化时传入) final String url; final Map<String, String> headers; final Map<String, String> fields; final List<String>? filePaths; final List<String>? fileKeys; ExpiredTokenRetryPolicy({ required this.url, required this.headers, required this.fields, this.filePaths, this.fileKeys, }); @override Future<bool> shouldAttemptRetryOnResponse(http.BaseResponse response) async { if (response.statusCode == 401) { return await refreshToken(); } return false; } @override Future<BaseRequest> retryRequest(BaseRequest request, BaseResponse response) async { // 重试时重新构建Multipart请求 return await buildMultipartRequest(url, headers, fields, filePaths, fileKeys); } }
方案2:将文件内容读入内存生成可复用的MultipartFile
把文件内容一次性读取到内存中,生成基于字节数组的MultipartFile,这样每次重试都可以重新生成流(适合小文件场景)。
代码示例:
Future<http.MultipartFile> createReusableMultipartFile(String key, String path) async { final fileBytes = await File(path).readAsBytes(); return http.MultipartFile.fromBytes( key, fileBytes, filename: path.split('/').last, ); }
在构建请求时使用该方法替代fromPath,即可实现流的重复读取。
关键注意事项
- 使用
fromPath时,每次调用都会重新打开文件流,不会占用过多内存,适合大文件场景。 - 基于字节数组的方式虽然能复用流,但大文件会导致内存占用过高,需谨慎使用。
内容的提问来源于stack exchange,提问作者Jostin Akkara
相关产品推荐
相关产品推荐

