Adds lastModified property and prevents caching if file already exists (Android)
This commit is contained in:
parent
c4d80c5d7c
commit
ea601246fd
|
@ -2,9 +2,7 @@ package com.mr.flutter.plugin.filepicker;
|
|||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FileInfo {
|
||||
|
||||
|
@ -13,14 +11,16 @@ public class FileInfo {
|
|||
final String name;
|
||||
final int size;
|
||||
final byte[] bytes;
|
||||
final long lastModified;
|
||||
final boolean isDirectory;
|
||||
|
||||
public FileInfo(Uri uri, String path, String name, int size, byte[] bytes, boolean isDirectory) {
|
||||
public FileInfo(Uri uri, String path, String name, int size, byte[] bytes, boolean isDirectory, long lastModified) {
|
||||
this.uri = uri;
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
this.bytes = bytes;
|
||||
this.lastModified = lastModified;
|
||||
this.isDirectory = isDirectory;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ public class FileInfo {
|
|||
private String path;
|
||||
private String name;
|
||||
private int size;
|
||||
private long lastModified;
|
||||
private byte[] bytes;
|
||||
private boolean isDirectory;
|
||||
|
||||
|
@ -58,14 +59,19 @@ public class FileInfo {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder withDirectory(String directory){
|
||||
this.path = directory;
|
||||
this.isDirectory = directory != null;
|
||||
public Builder withDirectory(String path){
|
||||
this.path = path;
|
||||
this.isDirectory = path != null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder lastModifiedAt(long timeStamp){
|
||||
this.lastModified = timeStamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileInfo build() {
|
||||
return new FileInfo(this.uri, this.path, this.name, this.size, this.bytes, this.isDirectory);
|
||||
return new FileInfo(this.uri, this.path, this.name, this.size, this.bytes, this.isDirectory, this.lastModified);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,6 +84,7 @@ public class FileInfo {
|
|||
data.put("size", size);
|
||||
data.put("bytes", bytes);
|
||||
data.put("isDirectory", isDirectory);
|
||||
data.put("lastModified", lastModified);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,11 +111,20 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener
|
|||
|
||||
Log.d(FilePickerDelegate.TAG, "[SingleFilePick] File URI:" + uri.toString());
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
final FileInfo file = type.equals("dir") ? FileUtils.getFullPathFromTreeUri(uri, activity) : FileUtils.openFileStream(FilePickerDelegate.this.activity, uri);
|
||||
if(file != null) {
|
||||
files.add(file);
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && type.equals("dir")) {
|
||||
final String dirPath = FileUtils.getFullPathFromTreeUri(uri, activity);
|
||||
if(dirPath != null) {
|
||||
finishWithSuccess(dirPath);
|
||||
} else {
|
||||
finishWithError("unknown_path", "Failed to retrieve directory path.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final FileInfo file = FileUtils.openFileStream(FilePickerDelegate.this.activity, uri);
|
||||
|
||||
if(file != null) {
|
||||
files.add(file);
|
||||
}
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
|
@ -233,7 +242,7 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener
|
|||
this.startFileExplorer();
|
||||
}
|
||||
|
||||
private void finishWithSuccess(final ArrayList<FileInfo> files) {
|
||||
private void finishWithSuccess(Object data) {
|
||||
if (eventSink != null) {
|
||||
this.dispatchEventStatus(false);
|
||||
}
|
||||
|
@ -241,10 +250,13 @@ public class FilePickerDelegate implements PluginRegistry.ActivityResultListener
|
|||
// Temporary fix, remove this null-check after Flutter Engine 1.14 has landed on stable
|
||||
if (this.pendingResult != null) {
|
||||
|
||||
final ArrayList<HashMap<String, Object>> data = new ArrayList<>();
|
||||
if(data != null && !(data instanceof String)) {
|
||||
final ArrayList<HashMap<String, Object>> files = new ArrayList<>();
|
||||
|
||||
for(FileInfo file : files) {
|
||||
data.add(file.toMap());
|
||||
for (FileInfo file : (ArrayList<FileInfo>)data) {
|
||||
files.add(file.toMap());
|
||||
}
|
||||
data = files;
|
||||
}
|
||||
|
||||
this.pendingResult.success(data);
|
||||
|
|
|
@ -17,8 +17,11 @@ import android.webkit.MimeTypeMap;
|
|||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -32,106 +35,6 @@ public class FileUtils {
|
|||
private static final String TAG = "FilePickerUtils";
|
||||
private static final String PRIMARY_VOLUME_NAME = "primary";
|
||||
|
||||
public static String getPath(final Uri uri, final Context context) {
|
||||
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
|
||||
if (isKitKat) {
|
||||
return getForApi19(context, uri);
|
||||
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||
if (isGooglePhotosUri(uri)) {
|
||||
return uri.getLastPathSegment();
|
||||
}
|
||||
return getDataColumn(context, uri, null, null);
|
||||
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
return uri.getPath();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@TargetApi(19)
|
||||
@SuppressWarnings("deprecation")
|
||||
private static String getForApi19(final Context context, final Uri uri) {
|
||||
Log.e(TAG, "Getting for API 19 or above" + uri);
|
||||
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||
Log.e(TAG, "Document URI");
|
||||
if (isExternalStorageDocument(uri)) {
|
||||
Log.e(TAG, "External Document URI");
|
||||
final String docId = DocumentsContract.getDocumentId(uri);
|
||||
final String[] split = docId.split(":");
|
||||
final String type = split[0];
|
||||
if ("primary".equalsIgnoreCase(type)) {
|
||||
Log.e(TAG, "Primary External Document URI");
|
||||
return Environment.getExternalStorageDirectory() + (split.length > 1 ? ("/" + split[1]) : "");
|
||||
}
|
||||
} else if (isDownloadsDocument(uri)) {
|
||||
Log.e(TAG, "Downloads External Document URI");
|
||||
String id = DocumentsContract.getDocumentId(uri);
|
||||
|
||||
if (!TextUtils.isEmpty(id)) {
|
||||
if (id.startsWith("raw:")) {
|
||||
return id.replaceFirst("raw:", "");
|
||||
}
|
||||
final String[] contentUriPrefixesToTry = new String[]{
|
||||
"content://downloads/public_downloads",
|
||||
"content://downloads/my_downloads",
|
||||
"content://downloads/all_downloads"
|
||||
};
|
||||
if (id.contains(":")) {
|
||||
id = id.split(":")[1];
|
||||
}
|
||||
for (final String contentUriPrefix : contentUriPrefixesToTry) {
|
||||
try {
|
||||
final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
|
||||
final String path = getDataColumn(context, contentUri, null, null);
|
||||
if (path != null) {
|
||||
return path;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Something went wrong while retrieving document path: " + e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (isMediaDocument(uri)) {
|
||||
Log.e(TAG, "Media Document URI");
|
||||
final String docId = DocumentsContract.getDocumentId(uri);
|
||||
final String[] split = docId.split(":");
|
||||
final String type = split[0];
|
||||
|
||||
Uri contentUri = null;
|
||||
if ("image".equals(type)) {
|
||||
Log.i(TAG, "Image Media Document URI");
|
||||
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("video".equals(type)) {
|
||||
Log.i(TAG, "Video Media Document URI");
|
||||
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||
} else if ("audio".equals(type)) {
|
||||
Log.i(TAG, "Audio Media Document URI");
|
||||
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
}
|
||||
|
||||
final String selection = MediaStore.Images.Media._ID + "=?";
|
||||
final String[] selectionArgs = new String[]{
|
||||
split[1]
|
||||
};
|
||||
|
||||
return getDataColumn(context, contentUri, selection, selectionArgs);
|
||||
}
|
||||
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||
Log.e(TAG, "NO DOCUMENT URI - CONTENT: " + uri.getPath());
|
||||
if (isGooglePhotosUri(uri)) {
|
||||
return uri.getLastPathSegment();
|
||||
} else if (isDropBoxUri(uri)) {
|
||||
return null;
|
||||
}
|
||||
return getDataColumn(context, uri, null, null);
|
||||
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
Log.e(TAG, "No DOCUMENT URI - FILE: " + uri.getPath());
|
||||
return uri.getPath();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String[] getMimeTypes(final ArrayList<String> allowedExtensions) {
|
||||
|
||||
if (allowedExtensions == null || allowedExtensions.isEmpty()) {
|
||||
|
@ -153,29 +56,6 @@ public class FileUtils {
|
|||
return mimes.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private static String getDataColumn(final Context context, final Uri uri, final String selection,
|
||||
final String[] selectionArgs) {
|
||||
Cursor cursor = null;
|
||||
final String column = MediaStore.Images.Media.DATA;
|
||||
final String[] projection = {
|
||||
column
|
||||
};
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
|
||||
null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int index = cursor.getColumnIndexOrThrow(column);
|
||||
return cursor.getString(index);
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getFileName(Uri uri, final Context context) {
|
||||
String result = null;
|
||||
|
||||
|
@ -245,41 +125,59 @@ public class FileUtils {
|
|||
final String path = context.getCacheDir().getAbsolutePath() + "/file_picker/" + (fileName != null ? fileName : new Random().nextInt(100000));
|
||||
|
||||
final File file = new File(path);
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
try {
|
||||
fos = new FileOutputStream(path);
|
||||
if(file.exists()) {
|
||||
int size = (int) file.length();
|
||||
byte[] bytes = new byte[size];
|
||||
|
||||
try {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final InputStream in = context.getContentResolver().openInputStream(uri);
|
||||
|
||||
final byte[] buffer = new byte[8192];
|
||||
int len = 0;
|
||||
|
||||
while ((len = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
fileInfo.withData(out.toByteArray());
|
||||
out.writeTo(fos);
|
||||
out.flush();
|
||||
} finally {
|
||||
fos.getFD().sync();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (final IOException | NullPointerException ex) {
|
||||
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
|
||||
buf.read(bytes, 0, bytes.length);
|
||||
buf.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(TAG, "File not found: " + e.getMessage(), null);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to close file streams: " + e.getMessage(), null);
|
||||
}
|
||||
fileInfo.withData(bytes);
|
||||
} else {
|
||||
|
||||
file.getParentFile().mkdirs();
|
||||
try {
|
||||
fos = new FileOutputStream(path);
|
||||
try {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final InputStream in = context.getContentResolver().openInputStream(uri);
|
||||
|
||||
final byte[] buffer = new byte[8192];
|
||||
int len = 0;
|
||||
|
||||
while ((len = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
fileInfo.withData(out.toByteArray());
|
||||
out.writeTo(fos);
|
||||
out.flush();
|
||||
} finally {
|
||||
fos.getFD().sync();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (final IOException | NullPointerException ex) {
|
||||
Log.e(TAG, "Failed to close file streams: " + e.getMessage(), null);
|
||||
return null;
|
||||
}
|
||||
Log.e(TAG, "Failed to retrieve path: " + e.getMessage(), null);
|
||||
return null;
|
||||
}
|
||||
Log.e(TAG, "Failed to retrieve path: " + e.getMessage(), null);
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.d(TAG, "File loaded and cached at:" + path);
|
||||
|
||||
fileInfo
|
||||
.lastModifiedAt(file.lastModified())
|
||||
.withPath(path)
|
||||
.withName(fileName)
|
||||
.withSize(Integer.parseInt(String.valueOf(file.length()/1024)))
|
||||
|
@ -289,7 +187,7 @@ public class FileUtils {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public static FileInfo getFullPathFromTreeUri(@Nullable final Uri treeUri, Context con) {
|
||||
public static String getFullPathFromTreeUri(@Nullable final Uri treeUri, Context con) {
|
||||
if (treeUri == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -300,7 +198,7 @@ public class FileUtils {
|
|||
fileInfo.withUri(treeUri);
|
||||
|
||||
if (volumePath == null) {
|
||||
return fileInfo.withDirectory(File.separator).build();
|
||||
return File.separator;
|
||||
}
|
||||
|
||||
if (volumePath.endsWith(File.separator))
|
||||
|
@ -313,13 +211,13 @@ public class FileUtils {
|
|||
|
||||
if (documentPath.length() > 0) {
|
||||
if (documentPath.startsWith(File.separator)) {
|
||||
return fileInfo.withDirectory(volumePath + documentPath).build();
|
||||
return volumePath + documentPath;
|
||||
}
|
||||
else {
|
||||
return fileInfo.withDirectory(volumePath + File.separator + documentPath).build();
|
||||
return volumePath + File.separator + documentPath;
|
||||
}
|
||||
} else {
|
||||
return fileInfo.withDirectory(volumePath).build();
|
||||
return volumePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,24 +273,4 @@ public class FileUtils {
|
|||
else return File.separator;
|
||||
}
|
||||
|
||||
private static boolean isDropBoxUri(final Uri uri) {
|
||||
return "com.dropbox.android.FileCache".equals(uri.getAuthority());
|
||||
}
|
||||
|
||||
private static boolean isExternalStorageDocument(final Uri uri) {
|
||||
return "com.android.externalstorage.documents".equals(uri.getAuthority());
|
||||
}
|
||||
|
||||
private static boolean isDownloadsDocument(final Uri uri) {
|
||||
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
|
||||
}
|
||||
|
||||
private static boolean isMediaDocument(final Uri uri) {
|
||||
return "com.android.providers.media.documents".equals(uri.getAuthority());
|
||||
}
|
||||
|
||||
private static boolean isGooglePhotosUri(final Uri uri) {
|
||||
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
|||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
String _fileName;
|
||||
List<PlatformFile> _paths;
|
||||
String _directoryPath;
|
||||
String _extension;
|
||||
bool _loadingPath = false;
|
||||
bool _multiPick = false;
|
||||
|
@ -27,7 +28,8 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
|||
void _openFileExplorer() async {
|
||||
setState(() => _loadingPath = true);
|
||||
try {
|
||||
_paths = (await FilePicker.instance.pickFiles(
|
||||
_directoryPath = null;
|
||||
_paths = (await FilePicker.platform.pickFiles(
|
||||
type: _pickingType,
|
||||
allowMultiple: _multiPick,
|
||||
allowedExtensions: (_extension?.isNotEmpty ?? false) ? _extension?.replaceAll(' ', '')?.split(',') : null,
|
||||
|
@ -46,7 +48,7 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
|||
}
|
||||
|
||||
void _clearCachedFiles() {
|
||||
FilePicker.instance.clearTemporaryFiles().then((result) {
|
||||
FilePicker.platform.clearTemporaryFiles().then((result) {
|
||||
_scaffoldKey.currentState.showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: result ? Colors.green : Colors.red,
|
||||
|
@ -57,8 +59,8 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
|||
}
|
||||
|
||||
void _selectFolder() {
|
||||
FilePicker.instance.getDirectoryPath().then((value) {
|
||||
setState(() => _paths = [value]);
|
||||
FilePicker.platform.getDirectoryPath().then((value) {
|
||||
setState(() => _directoryPath = value);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -161,30 +163,35 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
|||
padding: const EdgeInsets.only(bottom: 10.0),
|
||||
child: const CircularProgressIndicator(),
|
||||
)
|
||||
: _paths != null
|
||||
? Container(
|
||||
padding: const EdgeInsets.only(bottom: 30.0),
|
||||
height: MediaQuery.of(context).size.height * 0.50,
|
||||
child: Scrollbar(
|
||||
child: ListView.separated(
|
||||
itemCount: _paths != null && _paths.isNotEmpty ? _paths.length : 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final bool isMultiPath = _paths != null && _paths.isNotEmpty;
|
||||
final String name =
|
||||
'File $index: ' + (isMultiPath ? _paths.map((e) => e.name).toList()[index] : _fileName ?? '...');
|
||||
final path = _paths.map((e) => e.path).toList()[index].toString();
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
name,
|
||||
),
|
||||
subtitle: Text(path),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) => const Divider(),
|
||||
)),
|
||||
: _directoryPath != null
|
||||
? ListTile(
|
||||
title: Text('Directory path'),
|
||||
subtitle: Text(_directoryPath),
|
||||
)
|
||||
: const SizedBox(),
|
||||
: _paths != null
|
||||
? Container(
|
||||
padding: const EdgeInsets.only(bottom: 30.0),
|
||||
height: MediaQuery.of(context).size.height * 0.50,
|
||||
child: Scrollbar(
|
||||
child: ListView.separated(
|
||||
itemCount: _paths != null && _paths.isNotEmpty ? _paths.length : 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final bool isMultiPath = _paths != null && _paths.isNotEmpty;
|
||||
final String name =
|
||||
'File $index: ' + (isMultiPath ? _paths.map((e) => e.name).toList()[index] : _fileName ?? '...');
|
||||
final path = _paths.map((e) => e.path).toList()[index].toString();
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
name,
|
||||
),
|
||||
subtitle: Text(path),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) => const Divider(),
|
||||
)),
|
||||
)
|
||||
: const SizedBox(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -34,9 +34,9 @@ abstract class FilePicker extends PlatformInterface {
|
|||
|
||||
static FilePicker _instance = FilePickerIO();
|
||||
|
||||
static FilePicker get instance => _instance;
|
||||
static FilePicker get platform => _instance;
|
||||
|
||||
static set instance(FilePicker instance) {
|
||||
static set platform(FilePicker instance) {
|
||||
PlatformInterface.verifyToken(instance, _token);
|
||||
_instance = instance;
|
||||
}
|
||||
|
@ -71,5 +71,5 @@ abstract class FilePicker extends PlatformInterface {
|
|||
///
|
||||
/// On Android, this requires to be running on SDK 21 or above, else won't work.
|
||||
/// Returns `null` if folder path couldn't be resolved.
|
||||
Future<PlatformFile> getDirectoryPath() async => throw UnimplementedError('getDirectoryPath() has not been implemented.');
|
||||
Future<String> getDirectoryPath() async => throw UnimplementedError('getDirectoryPath() has not been implemented.');
|
||||
}
|
||||
|
|
|
@ -29,12 +29,9 @@ class FilePickerIO extends FilePicker {
|
|||
Future<bool> clearTemporaryFiles() async => _channel.invokeMethod<bool>('clear');
|
||||
|
||||
@override
|
||||
Future<PlatformFile> getDirectoryPath() async {
|
||||
Future<String> getDirectoryPath() async {
|
||||
try {
|
||||
String result = await _channel.invokeMethod('dir', {});
|
||||
if (result != null) {
|
||||
return PlatformFile(path: result, isDirectory: true);
|
||||
}
|
||||
return await _channel.invokeMethod('dir', {});
|
||||
} on PlatformException catch (ex) {
|
||||
if (ex.code == "unknown_path") {
|
||||
print(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:html' as html;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
|
@ -13,7 +14,7 @@ class FilePickerWeb extends FilePicker {
|
|||
static final FilePickerWeb platform = FilePickerWeb._();
|
||||
|
||||
static void registerWith(Registrar registrar) {
|
||||
FilePicker.instance = platform;
|
||||
FilePicker.platform = platform;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -40,10 +41,14 @@ class FilePickerWeb extends FilePicker {
|
|||
List<PlatformFile> pickedFiles = [];
|
||||
|
||||
reader.onLoadEnd.listen((e) {
|
||||
final Uint8List bytes = Base64Decoder().convert(reader.result.toString().split(",").last);
|
||||
|
||||
pickedFiles.add(
|
||||
PlatformFile(
|
||||
name: uploadInput.value.replaceAll('\\', '/'),
|
||||
bytes: Base64Decoder().convert(reader.result.toString().split(",").last),
|
||||
path: uploadInput.value,
|
||||
size: bytes.length ~/ 1024,
|
||||
bytes: bytes,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
class PlatformFile {
|
||||
PlatformFile({
|
||||
const PlatformFile({
|
||||
this.path,
|
||||
this.uri,
|
||||
this.name,
|
||||
|
@ -28,7 +28,9 @@ class PlatformFile {
|
|||
/// manipulate the original file (read, write, delete).
|
||||
///
|
||||
/// Android: it can be either content:// or file:// url.
|
||||
///
|
||||
/// iOS: a file:// URL below a document provider (like iCloud).
|
||||
///
|
||||
/// Web: Not supported, will be always `null`.
|
||||
final String uri;
|
||||
|
||||
|
@ -46,5 +48,5 @@ class PlatformFile {
|
|||
final bool isDirectory;
|
||||
|
||||
/// File extension for this file.
|
||||
String get extension => name.split('/').last;
|
||||
String get extension => name?.split('/')?.last;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue