2020-09-07 19:06:18 +00:00
|
|
|
import 'dart:async';
|
2020-09-24 20:59:18 +00:00
|
|
|
import 'dart:html';
|
2020-09-11 13:53:18 +00:00
|
|
|
import 'dart:typed_data';
|
2020-09-07 19:06:18 +00:00
|
|
|
|
|
|
|
import 'package:file_picker/file_picker.dart';
|
|
|
|
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
|
|
|
|
|
|
|
import 'file_picker_result.dart';
|
|
|
|
import 'platform_file.dart';
|
|
|
|
|
|
|
|
class FilePickerWeb extends FilePicker {
|
2020-09-24 20:59:18 +00:00
|
|
|
Element _target;
|
|
|
|
final String _kFilePickerInputsDomId = '__file_picker_web-file-input';
|
|
|
|
|
2020-11-12 17:28:57 +00:00
|
|
|
final int _readStreamChunkSize = 1000 * 1000; // 1 MB
|
|
|
|
|
2020-09-07 19:06:18 +00:00
|
|
|
static final FilePickerWeb platform = FilePickerWeb._();
|
|
|
|
|
2020-09-24 20:59:18 +00:00
|
|
|
FilePickerWeb._() {
|
|
|
|
_target = _ensureInitialized(_kFilePickerInputsDomId);
|
|
|
|
}
|
|
|
|
|
2020-09-07 19:06:18 +00:00
|
|
|
static void registerWith(Registrar registrar) {
|
2020-09-11 13:53:18 +00:00
|
|
|
FilePicker.platform = platform;
|
2020-09-07 19:06:18 +00:00
|
|
|
}
|
|
|
|
|
2020-09-24 20:59:18 +00:00
|
|
|
/// Initializes a DOM container where we can host input elements.
|
|
|
|
Element _ensureInitialized(String id) {
|
|
|
|
Element target = querySelector('#$id');
|
|
|
|
if (target == null) {
|
|
|
|
final Element targetElement = Element.tag('flt-file-picker-inputs')
|
|
|
|
..id = id;
|
|
|
|
|
|
|
|
querySelector('body').children.add(targetElement);
|
|
|
|
target = targetElement;
|
|
|
|
}
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2020-09-07 19:06:18 +00:00
|
|
|
@override
|
|
|
|
Future<FilePickerResult> pickFiles({
|
|
|
|
FileType type = FileType.any,
|
|
|
|
List<String> allowedExtensions,
|
|
|
|
bool allowMultiple = false,
|
|
|
|
Function(FilePickerStatus) onFileLoading,
|
|
|
|
bool allowCompression,
|
2020-09-11 17:01:34 +00:00
|
|
|
bool withData = true,
|
2020-11-12 17:28:57 +00:00
|
|
|
bool withReadStream = false,
|
2020-09-07 19:06:18 +00:00
|
|
|
}) async {
|
2020-09-11 17:37:45 +00:00
|
|
|
final Completer<List<PlatformFile>> filesCompleter =
|
|
|
|
Completer<List<PlatformFile>>();
|
2020-09-07 19:06:18 +00:00
|
|
|
|
|
|
|
String accept = _fileType(type, allowedExtensions);
|
2020-09-24 20:59:18 +00:00
|
|
|
InputElement uploadInput = FileUploadInputElement();
|
2020-09-07 19:06:18 +00:00
|
|
|
uploadInput.draggable = true;
|
|
|
|
uploadInput.multiple = allowMultiple;
|
|
|
|
uploadInput.accept = accept;
|
|
|
|
|
2020-09-24 20:59:18 +00:00
|
|
|
bool changeEventTriggered = false;
|
|
|
|
void changeEventListener(e) {
|
|
|
|
if (changeEventTriggered) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
changeEventTriggered = true;
|
2020-09-07 19:06:18 +00:00
|
|
|
|
2020-09-24 20:59:18 +00:00
|
|
|
final List<File> files = uploadInput.files;
|
|
|
|
final List<PlatformFile> pickedFiles = [];
|
2020-09-07 19:06:18 +00:00
|
|
|
|
2020-11-12 17:28:57 +00:00
|
|
|
void addPickedFile(
|
|
|
|
File file,
|
|
|
|
Uint8List bytes,
|
|
|
|
String path,
|
|
|
|
Stream<List<int>> readStream,
|
|
|
|
) {
|
2020-09-24 20:59:18 +00:00
|
|
|
pickedFiles.add(PlatformFile(
|
|
|
|
name: file.name,
|
|
|
|
path: path,
|
2020-11-12 17:28:57 +00:00
|
|
|
size: bytes != null ? bytes.length ~/ 1024 : file.size,
|
2020-09-24 20:59:18 +00:00
|
|
|
bytes: bytes,
|
2020-11-12 17:28:57 +00:00
|
|
|
readStream: readStream,
|
2020-09-24 20:59:18 +00:00
|
|
|
));
|
2020-09-07 19:06:18 +00:00
|
|
|
|
|
|
|
if (pickedFiles.length >= files.length) {
|
|
|
|
filesCompleter.complete(pickedFiles);
|
|
|
|
}
|
2020-09-24 20:59:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
files.forEach((File file) {
|
2020-11-12 17:28:57 +00:00
|
|
|
if (withReadStream) {
|
|
|
|
addPickedFile(file, null, null, _openFileReadStream(file));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-24 20:59:18 +00:00
|
|
|
if (!withData) {
|
|
|
|
final FileReader reader = FileReader();
|
|
|
|
reader.onLoadEnd.listen((e) {
|
2020-11-12 17:28:57 +00:00
|
|
|
addPickedFile(file, null, reader.result, null);
|
2020-09-24 20:59:18 +00:00
|
|
|
});
|
|
|
|
reader.readAsDataUrl(file);
|
|
|
|
return;
|
|
|
|
}
|
2020-09-07 19:06:18 +00:00
|
|
|
|
2020-09-24 20:59:18 +00:00
|
|
|
final FileReader reader = FileReader();
|
|
|
|
reader.onLoadEnd.listen((e) {
|
2020-11-12 17:28:57 +00:00
|
|
|
addPickedFile(file, reader.result, null, null);
|
2020-09-24 20:59:18 +00:00
|
|
|
});
|
|
|
|
reader.readAsArrayBuffer(file);
|
2020-09-07 19:06:18 +00:00
|
|
|
});
|
2020-09-24 20:59:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uploadInput.onChange.listen(changeEventListener);
|
|
|
|
uploadInput.addEventListener('change', changeEventListener);
|
|
|
|
|
|
|
|
//Add input element to the page body
|
|
|
|
_target.children.clear();
|
|
|
|
_target.children.add(uploadInput);
|
|
|
|
uploadInput.click();
|
|
|
|
|
2020-09-07 19:06:18 +00:00
|
|
|
return FilePickerResult(await filesCompleter.future);
|
|
|
|
}
|
|
|
|
|
|
|
|
static String _fileType(FileType type, List<String> allowedExtensions) {
|
|
|
|
switch (type) {
|
|
|
|
case FileType.any:
|
|
|
|
return '';
|
|
|
|
|
|
|
|
case FileType.audio:
|
|
|
|
return 'audio/*';
|
|
|
|
|
|
|
|
case FileType.image:
|
|
|
|
return 'image/*';
|
|
|
|
|
|
|
|
case FileType.video:
|
|
|
|
return 'video/*';
|
|
|
|
|
|
|
|
case FileType.media:
|
|
|
|
return 'video/*|image/*';
|
|
|
|
|
|
|
|
case FileType.custom:
|
2020-09-11 17:37:45 +00:00
|
|
|
return allowedExtensions.fold(
|
|
|
|
'', (prev, next) => '${prev.isEmpty ? '' : '$prev,'} .$next');
|
2020-09-07 19:06:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
}
|
2020-11-12 17:28:57 +00:00
|
|
|
|
|
|
|
Stream<List<int>> _openFileReadStream(File file) async* {
|
|
|
|
final reader = FileReader();
|
|
|
|
|
|
|
|
int start = 0;
|
|
|
|
while (start < file.size) {
|
|
|
|
final end = start + _readStreamChunkSize > file.size
|
|
|
|
? file.size
|
|
|
|
: start + _readStreamChunkSize;
|
|
|
|
final blob = file.slice(start, end);
|
|
|
|
reader.readAsArrayBuffer(blob);
|
|
|
|
await reader.onLoad.first;
|
|
|
|
yield reader.result;
|
|
|
|
start += _readStreamChunkSize;
|
|
|
|
}
|
|
|
|
}
|
2020-09-07 19:06:18 +00:00
|
|
|
}
|