mirror of
https://github.com/lifegpc/eh_downloader_flutter.git
synced 2026-07-08 01:30:28 +08:00
rewrite file api
This commit is contained in:
@@ -31,38 +31,57 @@ class Path {
|
|||||||
return _currentExe;
|
return _currentExe;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 保存文件
|
|
||||||
Future<void> saveFile(
|
Future<void> saveFile(
|
||||||
String filenameWithoutExtension, String mimeType, Uint8List bytes,
|
String filenameWithoutExtension, String mimeType, Uint8List bytes,
|
||||||
{String dir = ""}) async {
|
{String dir = "", bool saveAs = true}) async {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
return saveFileWeb(bytes, mimeType, filenameWithoutExtension);
|
return saveFileWeb(bytes, mimeType, filenameWithoutExtension);
|
||||||
}
|
}
|
||||||
return _safChannel.invokeMethod(
|
final f = await openFile(filenameWithoutExtension, mimeType,
|
||||||
"saveFile", [filenameWithoutExtension, dir, mimeType, bytes]);
|
dir: dir, saveAs: saveAs);
|
||||||
|
try {
|
||||||
|
await f.write(bytes);
|
||||||
|
} finally {
|
||||||
|
await f.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SAFFile> openFile(String filenameWithoutExtension, String mimeType,
|
Future<SAFFile> openFile(String filenameWithoutExtension, String mimeType,
|
||||||
{String dir = ""}) async {
|
{String dir = "",
|
||||||
final fd = await _safChannel.invokeMethod<int>(
|
bool read = false,
|
||||||
"openFile", [filenameWithoutExtension, dir, mimeType]);
|
bool write = true,
|
||||||
return SAFFile(fd!);
|
bool append = false,
|
||||||
|
bool saveAs = true}) async {
|
||||||
|
if (!write) {
|
||||||
|
append = false;
|
||||||
|
}
|
||||||
|
final fd = await _safChannel.invokeMethod<int>("openFile",
|
||||||
|
[filenameWithoutExtension, dir, mimeType, read, write, append, saveAs]);
|
||||||
|
return SAFFile(fd!, read, write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SAFFile {
|
class SAFFile {
|
||||||
SAFFile(this._fd);
|
SAFFile(this._fd, this._read, this._write);
|
||||||
|
|
||||||
final int _fd;
|
final int _fd;
|
||||||
|
final bool _read;
|
||||||
|
final bool _write;
|
||||||
bool _disposed = false;
|
bool _disposed = false;
|
||||||
|
|
||||||
|
Future<Uint8List> read(int maxLen) async {
|
||||||
|
if (_disposed) throw Exception("File already closed");
|
||||||
|
if (!_read) throw Exception("File not opened for read");
|
||||||
|
return await Path._safChannel.invokeMethod("readFile", [_fd, maxLen]);
|
||||||
|
}
|
||||||
|
|
||||||
/// 写入文件,返回此次写入的字节数
|
/// 写入文件,返回此次写入的字节数
|
||||||
///
|
///
|
||||||
/// [data] 要写入文件的数据
|
/// [data] 要写入文件的数据
|
||||||
Future<int> write(Uint8List data) async {
|
Future<int> write(Uint8List data) async {
|
||||||
if (_disposed) throw Exception("File already closed");
|
if (_disposed) throw Exception("File already closed");
|
||||||
return await Path._safChannel
|
if (!_write) throw Exception("File not opened for write");
|
||||||
.invokeMethod("writeFile", [_fd, data]);
|
return await Path._safChannel.invokeMethod("writeFile", [_fd, data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
@@ -66,117 +67,79 @@ const gchar* get_ext_from_mime_type(const gchar* mime_type) {
|
|||||||
static void on_saf_channel_call(FlMethodChannel* channel, FlMethodCall* method_call,
|
static void on_saf_channel_call(FlMethodChannel* channel, FlMethodCall* method_call,
|
||||||
gpointer user_data) {
|
gpointer user_data) {
|
||||||
const gchar* method = fl_method_call_get_name(method_call);
|
const gchar* method = fl_method_call_get_name(method_call);
|
||||||
if (strcmp(method, "saveFile") == 0) {
|
if (g_strcmp0(method, "openFile") == 0) {
|
||||||
auto args = fl_method_call_get_args(method_call);
|
|
||||||
auto fileName = fl_value_get_string(fl_value_get_list_value(args, 0));
|
|
||||||
auto dir = fl_value_get_string(fl_value_get_list_value(args, 1));
|
|
||||||
auto mimeType = fl_value_get_string(fl_value_get_list_value(args, 2));
|
|
||||||
auto odata = fl_value_get_list_value(args, 3);
|
|
||||||
auto data = fl_value_get_uint8_list(odata);
|
|
||||||
auto dataLen = fl_value_get_length(odata);
|
|
||||||
if (!fileName || !dir || !mimeType || !data) {
|
|
||||||
fl_method_call_respond_error(method_call, "INVALID_ARGUMENTS", "Invalid arguments", nullptr, nullptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto dialog = gtk_file_chooser_dialog_new("Save File", nullptr, GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
|
||||||
"_Save", GTK_RESPONSE_ACCEPT,
|
|
||||||
nullptr);
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
||||||
auto ext = get_ext_from_mime_type(mimeType);
|
|
||||||
if (ext) {
|
|
||||||
auto gstr = g_string_new(fileName);
|
|
||||||
g_string_append(gstr, ext);
|
|
||||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), gstr->str);
|
|
||||||
g_string_free(gstr, TRUE);
|
|
||||||
} else {
|
|
||||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), fileName);
|
|
||||||
}
|
|
||||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
|
|
||||||
auto filter = gtk_file_filter_new();
|
|
||||||
gtk_file_filter_add_mime_type(filter, mimeType);
|
|
||||||
gtk_file_filter_set_name(filter, get_filter_name_from_mime_type(mimeType));
|
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
|
||||||
filter = gtk_file_filter_new();
|
|
||||||
gtk_file_filter_add_pattern(filter, "*");
|
|
||||||
gtk_file_filter_set_name(filter, "All files");
|
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
|
||||||
auto res = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
||||||
if (res == GTK_RESPONSE_ACCEPT) {
|
|
||||||
g_autoptr(GError) local_err = NULL;
|
|
||||||
auto file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(dialog));
|
|
||||||
GFileOutputStream* stream = g_file_replace(file, nullptr, FALSE, G_FILE_CREATE_NONE, nullptr, &local_err);
|
|
||||||
if (stream == nullptr) {
|
|
||||||
fl_method_call_respond_error(method_call, "SAVE_FILE_ERROR", local_err->message, nullptr, nullptr);
|
|
||||||
} else {
|
|
||||||
gboolean ok = g_output_stream_write_all(G_OUTPUT_STREAM(stream), data, dataLen, nullptr, nullptr, &local_err);
|
|
||||||
if (!ok) {
|
|
||||||
fl_method_call_respond_error(method_call, "SAVE_FILE_ERROR", local_err->message, nullptr, nullptr);
|
|
||||||
} else {
|
|
||||||
ok = g_output_stream_flush(G_OUTPUT_STREAM(stream), nullptr, &local_err);
|
|
||||||
if (!ok) {
|
|
||||||
fl_method_call_respond_error(method_call, "SAVE_FILE_ERROR", local_err->message, nullptr, nullptr);
|
|
||||||
} else {
|
|
||||||
ok = g_output_stream_close(G_OUTPUT_STREAM(stream), nullptr, &local_err);
|
|
||||||
if (!ok) {
|
|
||||||
fl_method_call_respond_error(method_call, "SAVE_FILE_ERROR", local_err->message, nullptr, nullptr);
|
|
||||||
} else {
|
|
||||||
fl_method_call_respond_success(method_call, nullptr, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_object_unref(stream);
|
|
||||||
}
|
|
||||||
g_object_unref(file);
|
|
||||||
} else {
|
|
||||||
fl_method_call_respond_error(method_call, "USER_CANCELED", "User canceled", nullptr, nullptr);
|
|
||||||
}
|
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
} else if (g_strcmp0(method, "openFile") == 0) {
|
|
||||||
auto args = fl_method_call_get_args(method_call);
|
auto args = fl_method_call_get_args(method_call);
|
||||||
auto fileName = fl_value_get_string(fl_value_get_list_value(args, 0));
|
auto fileName = fl_value_get_string(fl_value_get_list_value(args, 0));
|
||||||
auto dir = fl_value_get_string(fl_value_get_list_value(args, 1));
|
auto dir = fl_value_get_string(fl_value_get_list_value(args, 1));
|
||||||
auto mimeType = fl_value_get_string(fl_value_get_list_value(args, 2));
|
auto mimeType = fl_value_get_string(fl_value_get_list_value(args, 2));
|
||||||
|
auto readOnly = fl_value_get_bool(fl_value_get_list_value(args, 3));
|
||||||
|
auto writeOnly = fl_value_get_bool(fl_value_get_list_value(args, 4));
|
||||||
|
auto append = fl_value_get_bool(fl_value_get_list_value(args, 5));
|
||||||
|
auto saveAs = fl_value_get_bool(fl_value_get_list_value(args, 6));
|
||||||
|
std::string filename;
|
||||||
if (!fileName || !dir || !mimeType) {
|
if (!fileName || !dir || !mimeType) {
|
||||||
fl_method_call_respond_error(method_call, "INVALID_ARGUMENTS", "Invalid arguments", nullptr, nullptr);
|
fl_method_call_respond_error(method_call, "INVALID_ARGUMENTS", "Invalid arguments", nullptr, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto dialog = gtk_file_chooser_dialog_new("Save File", nullptr, GTK_FILE_CHOOSER_ACTION_SAVE,
|
if (saveAs) {
|
||||||
|
auto dialog = gtk_file_chooser_dialog_new("Save File", nullptr, GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
"_Save", GTK_RESPONSE_ACCEPT,
|
"_Save", GTK_RESPONSE_ACCEPT,
|
||||||
nullptr);
|
nullptr);
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||||
auto ext = get_ext_from_mime_type(mimeType);
|
auto ext = get_ext_from_mime_type(mimeType);
|
||||||
if (ext) {
|
if (ext) {
|
||||||
auto gstr = g_string_new(fileName);
|
auto gstr = g_string_new(fileName);
|
||||||
g_string_append(gstr, ext);
|
g_string_append(gstr, ext);
|
||||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), gstr->str);
|
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), gstr->str);
|
||||||
g_string_free(gstr, TRUE);
|
g_string_free(gstr, TRUE);
|
||||||
} else {
|
|
||||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), fileName);
|
|
||||||
}
|
|
||||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
|
|
||||||
auto filter = gtk_file_filter_new();
|
|
||||||
gtk_file_filter_add_mime_type(filter, mimeType);
|
|
||||||
gtk_file_filter_set_name(filter, get_filter_name_from_mime_type(mimeType));
|
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
|
||||||
filter = gtk_file_filter_new();
|
|
||||||
gtk_file_filter_add_pattern(filter, "*");
|
|
||||||
gtk_file_filter_set_name(filter, "All files");
|
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
|
||||||
auto res = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
||||||
if (res == GTK_RESPONSE_ACCEPT) {
|
|
||||||
auto filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
||||||
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
||||||
if (fd != -1) {
|
|
||||||
fl_method_call_respond_success(method_call, fl_value_new_int(fd), nullptr);
|
|
||||||
} else {
|
} else {
|
||||||
fl_method_call_respond_error(method_call, "OPEN_FILE_ERROR", g_strerror(errno), nullptr, nullptr);
|
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), fileName);
|
||||||
}
|
}
|
||||||
|
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
|
||||||
|
auto filter = gtk_file_filter_new();
|
||||||
|
gtk_file_filter_add_mime_type(filter, mimeType);
|
||||||
|
gtk_file_filter_set_name(filter, get_filter_name_from_mime_type(mimeType));
|
||||||
|
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||||
|
filter = gtk_file_filter_new();
|
||||||
|
gtk_file_filter_add_pattern(filter, "*");
|
||||||
|
gtk_file_filter_set_name(filter, "All files");
|
||||||
|
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||||
|
auto res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
|
if (res == GTK_RESPONSE_ACCEPT) {
|
||||||
|
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
|
} else {
|
||||||
|
fl_method_call_respond_error(method_call, "USER_CANCELED", "User canceled", nullptr, nullptr);
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
} else {
|
} else {
|
||||||
fl_method_call_respond_error(method_call, "USER_CANCELED", "User canceled", nullptr, nullptr);
|
filename = dir;
|
||||||
|
filename += "/";
|
||||||
|
filename += fileName;
|
||||||
|
auto ext = get_ext_from_mime_type(mimeType);
|
||||||
|
if (ext) {
|
||||||
|
filename += ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int flags = 0;
|
||||||
|
if (readOnly && writeOnly) {
|
||||||
|
flags |= O_RDWR | O_CREAT;
|
||||||
|
} else if (readOnly) {
|
||||||
|
flags |= O_RDONLY;
|
||||||
|
} else if (writeOnly) {
|
||||||
|
flags |= O_WRONLY | O_TRUNC | O_CREAT;
|
||||||
|
}
|
||||||
|
if (append) {
|
||||||
|
flags |= O_APPEND;
|
||||||
|
}
|
||||||
|
int fd = open(filename.c_str(), flags, 0644);
|
||||||
|
if (fd != -1) {
|
||||||
|
fl_method_call_respond_success(method_call, fl_value_new_int(fd), nullptr);
|
||||||
|
} else {
|
||||||
|
fl_method_call_respond_error(method_call, "OPEN_FILE_ERROR", g_strerror(errno), nullptr, nullptr);
|
||||||
}
|
}
|
||||||
gtk_widget_destroy(dialog);
|
|
||||||
} else if (g_strcmp0(method, "writeFile") == 0) {
|
} else if (g_strcmp0(method, "writeFile") == 0) {
|
||||||
auto args = fl_method_call_get_args(method_call);
|
auto args = fl_method_call_get_args(method_call);
|
||||||
auto fd = fl_value_get_int(fl_value_get_list_value(args, 0));
|
auto fd = fl_value_get_int(fl_value_get_list_value(args, 0));
|
||||||
@@ -202,6 +165,22 @@ static void on_saf_channel_call(FlMethodChannel* channel, FlMethodCall* method_c
|
|||||||
} else {
|
} else {
|
||||||
fl_method_call_respond_error(method_call, "CLOSE_FILE_ERROR", g_strerror(errno), nullptr, nullptr);
|
fl_method_call_respond_error(method_call, "CLOSE_FILE_ERROR", g_strerror(errno), nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
} else if (g_strcmp0(method, "readFile") == 0) {
|
||||||
|
auto args = fl_method_call_get_args(method_call);
|
||||||
|
auto fd = fl_value_get_int(fl_value_get_list_value(args, 0));
|
||||||
|
auto maxLen = fl_value_get_int(fl_value_get_list_value(args, 1));
|
||||||
|
auto data = g_malloc(maxLen);
|
||||||
|
if (!data) {
|
||||||
|
fl_method_call_respond_error(method_call, "OUT_OF_MEMORY", "Out of memory", nullptr, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto count = read(fd, data, maxLen);
|
||||||
|
if (count != (ssize_t)-1) {
|
||||||
|
fl_method_call_respond_success(method_call, fl_value_new_uint8_list((const uint8_t*)data, count), nullptr);
|
||||||
|
} else {
|
||||||
|
fl_method_call_respond_error(method_call, "READ_FILE_ERROR", g_strerror(errno), nullptr, nullptr);
|
||||||
|
}
|
||||||
|
g_free(data);
|
||||||
} else {
|
} else {
|
||||||
fl_method_call_respond_not_implemented(method_call, nullptr);
|
fl_method_call_respond_not_implemented(method_call, nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user