Skip to content

Commit

Permalink
Improve exceptions and documents for FormData and MultipartFile (#…
Browse files Browse the repository at this point in the history
…1714)

Help issues like #482 to understand what happened exactly.

### New Pull Request Checklist

- [x] I have read the
[Documentation](https://pub.dev/documentation/dio/latest/)
- [x] I have searched for a similar pull request in the
[project](https://github.com/cfug/dio/pulls) and found none
- [x] I have updated this branch with the latest `main` branch to avoid
conflicts (via merge from master or rebase)
- [ ] I have added the required tests to prove the fix/feature I'm
adding
- [x] I have updated the documentation (if necessary)
- [x] I have run the tests without failures
- [ ] I have updated the `CHANGELOG.md` in the corresponding package

### Additional context and info (if any)

As an improvement with comments and docs, it doesn't require a version
change.

---------

Signed-off-by: Alex Li <github@alexv525.com>
Co-authored-by: Peter Leibiger <kuhnroyal@gmail.com>
  • Loading branch information
AlexV525 and kuhnroyal committed Mar 6, 2023
1 parent 017588b commit 8a00f8d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
23 changes: 22 additions & 1 deletion dio/README-ZH.md
Expand Up @@ -36,6 +36,7 @@ dio 是一个强大的 Dart HTTP 请求库,支持全局配置、Restful API、
* [使用 application/x-www-form-urlencoded 编码](#使用-applicationx-www-form-urlencoded-编码)
* [发送 FormData](#发送-formdata)
* [多文件上传](#多文件上传)
* [复用 `FormData``MultipartFile`](#复用-formdata-和-multipartfile)
* [转换器](#转换器)
* [在 Flutter 中进行设置](#在-flutter-中进行设置)
* [其它示例](#其它示例)
Expand Down Expand Up @@ -569,7 +570,7 @@ final formData = FormData.fromMap({
final response = await dio.post('/info', data: formData);
```

> 注意: 只有 post 方法支持发送 FormData.
> 通常情况下只有 POST 方法支持发送 FormData
这里有一个完整的 [示例](../example/lib/formdata.dart)

Expand Down Expand Up @@ -604,6 +605,26 @@ formData.files.addAll([
]);
```

### 复用 `FormData``MultipartFile`

如果你在重复调用的请求中使用 `FormData` 或者 `MultipartFile`,确保你每次使用的都是新实例。
常见的错误做法是将 `FormData` 赋值给一个共享变量,在每次请求中都使用这个变量。
这样的操作会加大 **无法序列化** 的错误出现的可能性。
你可以像以下的代码一样编写你的请求以避免出现这样的错误:
```dart
Future<void> _repeatedlyRequest() async {
Future<FormData> createFormData() async {
return FormData.fromMap({
'name': 'dio',
'date': DateTime.now().toIso8601String(),
'file': await MultipartFile.fromFile('./text.txt',filename: 'upload.txt'),
});
}
await dio.post('some-url', data: await createFormData());
}
```

## 转换器

转换器 `Transformer` 用于对请求数据和响应数据进行编解码处理。
Expand Down
25 changes: 23 additions & 2 deletions dio/README.md
Expand Up @@ -37,6 +37,7 @@ timeout, and custom adapters etc.
* [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)
* [Sending FormData](#sending-formdata)
* [Multiple files upload](#multiple-files-upload)
* [Reuse `FormData`s and `MultipartFile`s](#reuse-formdata-s-and-multipartfile-s)
* [Transformer](#transformer)
* [In Flutter](#in-flutter)
* [Other example](#other-example)
Expand Down Expand Up @@ -596,12 +597,12 @@ and it supports uploading files.
final formData = FormData.fromMap({
'name': 'dio',
'date': DateTime.now().toIso8601String(),
'file': await MultipartFile.fromFile('./text.txt',filename: 'upload.txt')
'file': await MultipartFile.fromFile('./text.txt',filename: 'upload.txt'),
});
final response = await dio.post('/info', data: formData);
```

Note: `FormData` is only supported in POST methods.
> `FormData` is supported with the POST method typically.
There is a complete example [here](../example/lib/formdata.dart).

Expand Down Expand Up @@ -639,6 +640,26 @@ formData.files.addAll([
]);
```

### Reuse `FormData`s and `MultipartFile`s

You should make a new `FormData` or `MultipartFile` every time in repeated requests.
A typical wrong behavior is setting the `FormData` as a variable and using it in every request.
It can be easy for the *Cannot finalize* exceptions to occur.
To avoid that, write your requests like the below code:
```dart
Future<void> _repeatedlyRequest() async {
Future<FormData> createFormData() async {
return FormData.fromMap({
'name': 'dio',
'date': DateTime.now().toIso8601String(),
'file': await MultipartFile.fromFile('./text.txt',filename: 'upload.txt'),
});
}
await dio.post('some-url', data: await createFormData());
}
```

## Transformer

`Transformer` allows changes to the request/response data
Expand Down
6 changes: 5 additions & 1 deletion dio/lib/src/form_data.dart
Expand Up @@ -139,7 +139,11 @@ class FormData {

Stream<List<int>> finalize() {
if (isFinalized) {
throw StateError('Already finalized.');
throw StateError(
'The FormData has already been finalized. '
'This typically means you are using '
'the same FormData in repeated requests.',
);
}
_isFinalized = true;
final controller = StreamController<List<int>>(sync: false);
Expand Down
6 changes: 5 additions & 1 deletion dio/lib/src/multipart_file.dart
Expand Up @@ -131,7 +131,11 @@ class MultipartFile {

Stream<List<int>> finalize() {
if (isFinalized) {
throw StateError("Can't finalize a finalized MultipartFile.");
throw StateError(
'The MultipartFile has already been finalized. '
'This typically means you are using '
'the same MultipartFile in repeated requests.',
);
}
_isFinalized = true;
return _stream;
Expand Down

0 comments on commit 8a00f8d

Please sign in to comment.