问题描述
我的代码允许使用universal_html.InputElement uploadInput = universal_html.FileUploadInputElement();
网络Flutter 打开文件上传窗口,然后选择必要的文件以将其加载到项目中。如果用户未选择任何照片并单击关闭/取消窗口,则我想对此做出反应。 我如何理解该用户关闭窗口?
final completer = Completer<List<String>>();
universal_html.InputElement uploadInput = universal_html.FileUploadInputElement();
uploadInput.multiple = true;
uploadInput.accept = 'image/*';
uploadInput.click();
uploadInput.addEventListener('change',(e) async {
final files = uploadInput.files;
Iterable<Future<String>> resultsFutures = files.map((file) {
final reader = universal_html.FileReader();
reader.readAsDataUrl(file);
reader.onError.listen((error) => completer.completeError(error));
return reader.onLoad.first.then((_) => reader.result as String);
});
final results = await Future.wait(resultsFutures);
completer.complete(results);
});
universal_html.document.body.append(uploadInput);
final List<String> images = await completer.future;
uploadInput.remove();
解决方法
在包 file_picker 的 Web 实现中使用了一种管理此类事件的方法。
这是一个可以帮助您的代码示例(您还可以从包 here 中找到完整的实现):
import 'dart:html' as html;
import 'dart:async';
Future<html.File?> pickFile(String type) async {
final completer = Completer<List<html.File>?>();
final input = html.FileUploadInputElement() as html.InputElement;
input.accept = '$type/*';
var changeEventTriggered = false;
void changeEventListener(html.Event e) {
if (changeEventTriggered) return;
changeEventTriggered = true;
final files = input.files!;
final resultFuture = files.map<Future<html.File>>((file) async {
final reader = html.FileReader();
reader.readAsDataUrl(file);
reader.onError.listen(completer.completeError);
return file;
});
Future.wait(resultFuture).then((results) => completer.complete(results));
}
void cancelledEventListener(html.Event e) {
html.window.removeEventListener('focus',cancelledEventListener);
// This listener is called before the input changed event,// and the `uploadInput.files` value is still null
// Wait for results from js to dart
Future.delayed(Duration(milliseconds: 500)).then((value) {
if (!changeEventTriggered) {
changeEventTriggered = true;
completer.complete(null);
}
});
}
input.onChange.listen(changeEventListener);
input.addEventListener('change',changeEventListener);
// Listen focus event for cancelled
html.window.addEventListener('focus',cancelledEventListener);
input.click();
final results = await completer.future;
if (results == null || results.isEmpty) return null;
return results.first;
}
这个想法是依赖于 focus
事件的侦听器,因此当您在没有加载任何数据的情况下失去对文件选择器窗口的关注时,它将以 null
值完成您的未来。