如何在 http.MultipartRequest 请求中上传文件时获取进度事件
How to get progress event while uploading file on http.MultipartRequest request in flutter
我正在使用来自 package:http
的 MultipartRequest
上传文件。我正在成功上传文件,但我想了解正在上传的文件的进度。我怎样才能做到这一点?我当前的代码看起来像这样
Future submitFile(var report, File file) async {
var uri = Uri.parse(endpoint + "v1/reports");
var request = http.MultipartRequest("POST", uri);
await addHeaders(request.headers);
request.fields.addAll(Report.toMap(report));
if (file != null)
request.files.add(await http.MultipartFile.fromPath(
'report_resource',
file.path,
));
String response = "";
await (await request.send()).stream.forEach((message) {
response = response + String.fromCharCodes(message);
});
return response;
}
我搜索了解决方案,发现 this. And post 在某种程度上与我想要实现的不相似,因为他使用不同的客户端来处理请求。
也许我没有在正确的道路上寻找。
感谢帮助。
你能试试这个吗class因为我还没有测试它,让我知道你控制台上打印的任何东西。
class MF extends http.MultipartRequest{
MF(String method, Uri url) : super(method, url);
@override
Future<http.StreamedResponse> send() async {
var client = new Client();
int byteCount = 0;
Stream<List<int>> onDone<T>(Stream<List<int>> stream, void onDone()) =>
stream.transform(new StreamTransformer.fromHandlers(
handleDone: (sink) {
sink.close();
onDone();
},
handleData: (data, sink) {
byteCount += data.length;
print(byteCount);
sink.add(data);
},
),
);
try {
var response = await client.send(this);
var stream = onDone(response.stream, client.close);
return new StreamedResponse(new ByteStream(stream), response.statusCode,
contentLength: response.contentLength,
request: response.request,
headers: response.headers,
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase);
} catch (_) {
client.close();
rethrow;
}
}
}
用法:
而不是var request = http.MultipartRequest("POST", uri);
使用:
var request = MF("POST", uri);
等了一个星期左右。我没有得到回应。因此,我自己开发了一个插件来获得这种行为。包裹 link.
使用示例:
var request = MultipartRequest();
request.addFile("image", imagePath);
Response response = request.send();
response.onError = () {
print("Error");
};
response.onComplete = (response) {
print(response);
};
//Not 100% success
response.progress.listen((int progress) {
print("progress from response object " + progress.toString());
});
更新 2020 年 6 月 30 日
该软件包现在也支持 iOS。
这是我的看法:
// multipart_request.dart
import 'dart:async';
import 'package:http/http.dart' as http;
class MultipartRequest extends http.MultipartRequest {
/// Creates a new [MultipartRequest].
MultipartRequest(
String method,
Uri url, {
this.onProgress,
}) : super(method, url);
final void Function(int bytes, int totalBytes) onProgress;
/// Freezes all mutable fields and returns a single-subscription [ByteStream]
/// that will emit the request body.
http.ByteStream finalize() {
final byteStream = super.finalize();
if (onProgress == null) return byteStream;
final total = this.contentLength;
int bytes = 0;
final t = StreamTransformer.fromHandlers(
handleData: (List<int> data, EventSink<List<int>> sink) {
bytes += data.length;
onProgress(bytes, total);
if(total >= bytes) {
sink.add(data);
}
},
);
final stream = byteStream.transform(t);
return http.ByteStream(stream);
}
}
用法:
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart' show MediaType;
import 'multipart_request.dart';
final uri = 'https://...';
final request = MultipartRequest(
'POST',
uri,
onProgress: (int bytes, int total) {
final progress = bytes / total;
print('progress: $progress ($bytes/$total)');
},
);
request.headers['HeaderKey'] = 'header_value';
request.fields['form_key'] = 'form_value';
request.files.add(
await http.MultipartFile.fromPath(
'field_name',
'path/to/file',
contentType: MediaType('image', 'jpeg'),
),
);
final streamedResponse = await request.send();
我正在使用来自 package:http
的 MultipartRequest
上传文件。我正在成功上传文件,但我想了解正在上传的文件的进度。我怎样才能做到这一点?我当前的代码看起来像这样
Future submitFile(var report, File file) async {
var uri = Uri.parse(endpoint + "v1/reports");
var request = http.MultipartRequest("POST", uri);
await addHeaders(request.headers);
request.fields.addAll(Report.toMap(report));
if (file != null)
request.files.add(await http.MultipartFile.fromPath(
'report_resource',
file.path,
));
String response = "";
await (await request.send()).stream.forEach((message) {
response = response + String.fromCharCodes(message);
});
return response;
}
我搜索了解决方案,发现 this. And
也许我没有在正确的道路上寻找。 感谢帮助。
你能试试这个吗class因为我还没有测试它,让我知道你控制台上打印的任何东西。
class MF extends http.MultipartRequest{
MF(String method, Uri url) : super(method, url);
@override
Future<http.StreamedResponse> send() async {
var client = new Client();
int byteCount = 0;
Stream<List<int>> onDone<T>(Stream<List<int>> stream, void onDone()) =>
stream.transform(new StreamTransformer.fromHandlers(
handleDone: (sink) {
sink.close();
onDone();
},
handleData: (data, sink) {
byteCount += data.length;
print(byteCount);
sink.add(data);
},
),
);
try {
var response = await client.send(this);
var stream = onDone(response.stream, client.close);
return new StreamedResponse(new ByteStream(stream), response.statusCode,
contentLength: response.contentLength,
request: response.request,
headers: response.headers,
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase);
} catch (_) {
client.close();
rethrow;
}
}
}
用法:
而不是var request = http.MultipartRequest("POST", uri);
使用:
var request = MF("POST", uri);
等了一个星期左右。我没有得到回应。因此,我自己开发了一个插件来获得这种行为。包裹 link.
使用示例:
var request = MultipartRequest();
request.addFile("image", imagePath);
Response response = request.send();
response.onError = () {
print("Error");
};
response.onComplete = (response) {
print(response);
};
//Not 100% success
response.progress.listen((int progress) {
print("progress from response object " + progress.toString());
});
更新 2020 年 6 月 30 日
该软件包现在也支持 iOS。
这是我的看法:
// multipart_request.dart
import 'dart:async';
import 'package:http/http.dart' as http;
class MultipartRequest extends http.MultipartRequest {
/// Creates a new [MultipartRequest].
MultipartRequest(
String method,
Uri url, {
this.onProgress,
}) : super(method, url);
final void Function(int bytes, int totalBytes) onProgress;
/// Freezes all mutable fields and returns a single-subscription [ByteStream]
/// that will emit the request body.
http.ByteStream finalize() {
final byteStream = super.finalize();
if (onProgress == null) return byteStream;
final total = this.contentLength;
int bytes = 0;
final t = StreamTransformer.fromHandlers(
handleData: (List<int> data, EventSink<List<int>> sink) {
bytes += data.length;
onProgress(bytes, total);
if(total >= bytes) {
sink.add(data);
}
},
);
final stream = byteStream.transform(t);
return http.ByteStream(stream);
}
}
用法:
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart' show MediaType;
import 'multipart_request.dart';
final uri = 'https://...';
final request = MultipartRequest(
'POST',
uri,
onProgress: (int bytes, int total) {
final progress = bytes / total;
print('progress: $progress ($bytes/$total)');
},
);
request.headers['HeaderKey'] = 'header_value';
request.fields['form_key'] = 'form_value';
request.files.add(
await http.MultipartFile.fromPath(
'field_name',
'path/to/file',
contentType: MediaType('image', 'jpeg'),
),
);
final streamedResponse = await request.send();