-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
流响应接收的chunk与postman接收到的不一样 #2384
Labels
h: need more info
Further information is requested
h: need triage
This issue needs to be categorized
s: bug
Something isn't working
Comments
请提供最小可运行复现代码,而不是项目里的部分代码。 |
已重新编辑 |
@AlexV525 ==================================================== 针对您的问题,以下是解决方案: 问题1:Chunk合并问题这是由于 SSE 协议的数据帧分割方式决定的,Dio 的流式接收是按 TCP 包粒度返回的(不能保证和 SSE 的数据帧完全对应),需要手动处理数据分割。解决方案: StringBuffer buffer = StringBuffer(); // 新增缓冲区
await for (List<int> chunk in stream) {
String chunkString = utf8.decode(chunk);
buffer.write(chunkString);
// 按 SSE 协议分割数据帧(两个换行符)
while (true) {
int splitIndex = buffer.toString().indexOf('\n\n');
if (splitIndex == -1) break;
String frame = buffer.toString().substring(0, splitIndex);
buffer = StringBuffer(buffer.toString().substring(splitIndex + 2));
// 处理单个数据帧
processFrame(frame);
}
}
void processFrame(String frame) {
if (frame.isEmpty) return;
print("---frame start---");
print(frame);
print("---frame end---");
} 问题2:去除 data: 前缀在分割出单个数据帧后,可以这样处理: void processFrame(String frame) {
if (frame.startsWith('data: ')) {
String jsonStr = frame.substring(6); // 去掉 data: 前缀
if (jsonStr.trim() == '[DONE]') return;
try {
Map<String, dynamic> json = jsonDecode(jsonStr);
String content = json['choices'][0]['delta']['content'] ?? '';
print('收到内容: $content');
} catch (e) {
print('JSON 解析失败: $e');
}
}
} 完整优化代码void test() async {
Dio dio = Dio();
final response = await dio.request(
"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
options: Options(
method: "POST",
responseType: ResponseType.stream,
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer xxx",
},
),
data: {
"stream": true,
"model": "deepseek-v3",
"messages": [
{"role": "user", "content": "您好"}
],
},
);
final stream = (response.data as ResponseBody).stream;
StringBuffer buffer = StringBuffer();
await for (List<int> chunk in stream) {
String chunkString = utf8.decode(chunk);
buffer.write(chunkString);
while (true) {
int splitIndex = buffer.toString().indexOf('\n\n');
if (splitIndex == -1) break;
String frame = buffer.toString().substring(0, splitIndex);
buffer = StringBuffer(buffer.toString().substring(splitIndex + 2));
if (frame.startsWith('data: ')) {
String jsonStr = frame.substring(6);
if (jsonStr.trim() == '[DONE]') continue;
try {
Map<String, dynamic> json = jsonDecode(jsonStr);
String content = json['choices'][0]['delta']['content'] ?? '';
if (content.isNotEmpty) {
print('实时更新: $content');
}
} catch (e) {
print('解析异常: $e | 原始数据: $jsonStr');
}
}
}
}
} 关键点说明
这个方案可以保证:
Postman 和代码表现差异的原因是:Postman 的 SSE 实现会自动处理数据帧分割,而 Dio 的流式请求需要手动实现这一逻辑。 ====================================================
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
h: need more info
Further information is requested
h: need triage
This issue needs to be categorized
s: bug
Something isn't working
Package
dio
Version
5.8.0+1
Operating-System
Android
Adapter
Default Dio
Output of
flutter doctor -v
Dart Version
3.6.0
Steps to Reproduce
我使用阿里云百炼的Deepseek V3 api,使用dio进行流式接收。
dio代码:
注意 Bearer xxx 改成自己的
输出形式:
Expected Result
以postman为准
Actual Result
两个问题:
2.如何才能直接接收chuck内数据,而不带“data:”前缀?
附图:
dio
postman

The text was updated successfully, but these errors were encountered: