Flutter如何使用HttpClient向服务器发送数据并获取上传进度百分比
问题解答
结论
使用HttpClient完全可以获取上传进度,你当前的实现存在多处逻辑错误,修正后即可正常获取进度。
现有代码的错误点
- 重复提交请求体:同时调用了
request.addStream(streamUpload)和request.add(utf8.encode(body)),实际生效的是后者,前者的进度监听逻辑完全没有参与数据上传 - 自定义流没有输出数据:你在StreamTransformer的
handleData回调里只统计了字节长度,没有调用sink.add把数据传递到请求流里,addStream相当于上传了空内容 - 总长度计算错误:
body.length是字符串的字符数,UTF8编码后多字节字符的字节数会大于字符数,和实际上传的字节长度不匹配,会导致进度计算不准,甚至请求头Content-Length和实际长度不一致被服务端拒绝 - 缺少进度输出逻辑:仅统计了已上传字节数,没有对应的进度计算、输出逻辑,无法直观看到进度变化
修正后的实现代码
import 'dart:convert'; import 'dart:io'; void postDataWithProgress() async { HttpClient httpClient = HttpClient(); var url = "https://xxxxxxx/api/adddata"; HttpClientRequest request = await httpClient.postUrl(Uri.parse(url)).timeout(const Duration(seconds: 10)); var datavalue = { "listvideoname": ["a", "b", "c"], "listvideobase64": ["adahd", "ayuiary", "oukjfjka"] }; var body = json.encode(datavalue); // 编码为UTF8字节数组,计算正确的总字节长度 List<int> bodyBytes = utf8.encode(body); int totalByteLength = bodyBytes.length; int uploadedByteCount = 0; // 直接从字节数组构建上传流 Stream<List<int>> streamUpload = Stream.fromIterable([bodyBytes]) .transform(StreamTransformer.fromHandlers( handleData: (data, sink) { // 传递数据到请求流 sink.add(data); // 累加已上传字节 uploadedByteCount += data.length; // 计算并打印进度,保留两位小数 double progress = uploadedByteCount / totalByteLength * 100; print("当前上传进度:${progress.toStringAsFixed(2)}%"); }, handleDone: (sink) { sink.close(); }, handleError: (error, stackTrace, sink) { sink.addError(error, stackTrace); }, )); // 设置请求头 request.contentLength = totalByteLength; request.headers.set( "Content-Type", "application/json", preserveHeaderCase: true ); request.headers.set( "Authorization", "Bearer $token", preserveHeaderCase: true ); // 仅调用addStream上传,不要额外调用add方法 await request.addStream(streamUpload); HttpClientResponse response = await request.close(); if (response.statusCode == 200) { print("add data success"); } else { print("add data error,状态码:${response.statusCode}"); } httpClient.close(); }
额外优化建议
如果上传的内容体积很大,不建议把整个内容转成base64放到JSON里,会额外增加33%的体积,直接用multipart/form-data格式上传原文件,进度统计会更准确,内存占用也更低。
内容的提问来源于stack exchange,提问作者Syahrir
相关产品推荐
相关产品推荐

