要将上传或下载的任务信息存储在本地,你可以使用数据库或文件存储。下面是使用文件存储的示例代码:
dart
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'dart:io';
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'File Transfer',
home: TransferPage(),
);
}
}
class TransferPage extends StatefulWidget {
@override
_TransferPageState createState() => _TransferPageState();
}
class TransferTask {
final String name;
final String filePath;
final String fileUrl;
final String savePath;
final int totalBytes;
int transferredBytes;
bool isPaused;
TransferTask({
required this.name,
required this.filePath,
required this.fileUrl,
required this.savePath,
required this.totalBytes,
this.transferredBytes = 0,
this.isPaused = false,
});
Map<String, dynamic> toMap() {
return {
'name': name,
'filePath': filePath,
'fileUrl': fileUrl,
'savePath': savePath,
'totalBytes': totalBytes,
'transferredBytes': transferredBytes,
'isPaused': isPaused,
};
}
factory TransferTask.fromMap(Map<String, dynamic> map) {
return TransferTask(
name: map['name'],
filePath: map['filePath'],
fileUrl: map['fileUrl'],
savePath: map['savePath'],
totalBytes: map['totalBytes'],
transferredBytes: map['transferredBytes'],
isPaused: map['isPaused'],
);
}
String toJson() => json.encode(toMap());
factory TransferTask.fromJson(String source) =>
TransferTask.fromMap(json.decode(source));
}
class _TransferPageState extends State<TransferPage> {
Dio dio = Dio();
List<TransferTask> tasks = [];
@override
void initState() {
super.initState();
dio.interceptors.add(LogInterceptor());
// 从文件中加载任务信息
loadTasks();
}
void saveTasks() {
List<Map<String, dynamic>> taskList = tasks.map((task) => task.toMap()).toList();
String jsonTasks = json.encode(taskList);
File file = File('tasks.json');
file.writeAsStringSync(jsonTasks);
}
void loadTasks() {
File file = File('tasks.json');
if (file.existsSync()) {
String jsonTasks = file.readAsStringSync();
List<Map<String, dynamic>> taskList = json.decode(jsonTasks).cast<Map<String, dynamic>>();
tasks = taskList.map((taskMap) => TransferTask.fromMap(taskMap)).toList();
}
}
@override
void dispose() {
saveTasks(); // 在页面销毁时保存任务信息
super.dispose();
}
Future<void> uploadFile(TransferTask task) async {
try {
File file = File(task.filePath);
int sentBytes = 0;
if (await file.exists()) {
sentBytes = file.lengthSync(); // 获取已上传的字节数
FormData formData = FormData.fromMap({
'file': await MultipartFile.fromFile(
task.filePath,
start: sentBytes, // 设置上传起始位置
),
});
await dio.post(
'https://example.com/upload',
data: formData,
onSendProgress: (int sentBytes, int totalBytes) {
setState(() {
task.transferredBytes = sentBytes;
});
},
cancelToken: CancelToken()
..pauseOnCancel = true
..token = CancelToken().token,
);
}
} catch (e) {
print('上传失败: $e');
}
}
Future<void> downloadFile(TransferTask task) async {
try {
File file = File(task.savePath);
int receivedBytes = 0;
if (await file.exists()) {
receivedBytes = file.lengthSync(); // 获取已下载的字节数
}
await dio.download(
task.fileUrl,
task.savePath,
onReceiveProgress: (int receivedBytes, int totalBytes) {
setState(() {
task.transferredBytes = receivedBytes;
});
},
options: Options(
headers: {'range': 'bytes=$receivedBytes-'}, // 设置下载起始位置
),
cancelToken: CancelToken()
..pauseOnCancel = true
..token = CancelToken().token,
);
} catch (e) {
print('下载失败: $e');
}
}
Future<void> uploadAll() async {
for (TransferTask task in tasks) {
task.isPaused = false;
await uploadFile(task);
}
}
Future<void> downloadAll() async {
for (TransferTask task in tasks) {
task.isPaused = false;
await downloadFile(task);
}
}
void pauseUpload(TransferTask task) {
task.isPaused = true;
}
void continueUpload(TransferTask task) {
if (task.isPaused) {
task.isPaused = false;
uploadFile(task);
}
}
void pauseDownload(TransferTask task) {
task.isPaused = true;
}
void continueDownload(TransferTask task) {
if (task.isPaused) {
task.isPaused = false;
downloadFile(task);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('File Transfer'),
),
body: ListView.builder(
itemCount: tasks.length,
itemBuilder: (context, index) {
TransferTask task = tasks[index];
return ListTile(
title: Text(task.name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('已传输:${task.transferredBytes} / ${task.totalBytes} 字节'),
LinearProgressIndicator(
value: task.transferredBytes / task.totalBytes,
),
],
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (task.transferredBytes < task.totalBytes && !task.isPaused)
IconButton(
onPressed: () => pauseDownload(task),
icon: Icon(Icons.pause),
),
if (task.transferredBytes < task.totalBytes && task.isPaused)
IconButton(
onPressed: () => continueDownload(task),
icon: Icon(Icons.play_arrow),
),
if (task.transferredBytes == 0 && !task.isPaused)
IconButton(
onPressed: () => pauseUpload(task),
icon: Icon(Icons.pause),
),
if (task.transferredBytes == 0 && task.isPaused)
IconButton(
onPressed: () => continueUpload(task),
icon: Icon(Icons.play_arrow),
),
],
),
);
},
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: uploadAll,
child: Icon(Icons.cloud_upload),
),
SizedBox(width: 16),
FloatingActionButton(
onPressed: downloadAll,
child: Icon(Icons.cloud_download),
),
],
),
);
}
}
在上述代码中,我们将任务信息保存在名为 tasks.json 的文件中。使用 saveTasks 方法将任务信息转换为 JSON 格式并写入文件中,使用 loadTasks 方法从文件中加载任务信息并将其转换回对象数组。
在 _TransferPageState 类的 initState 方法中调用 loadTasks 来加载保存的任务信息,在 dispose 方法中调用 saveTasks 来保存任务信息。
这样,每次打开应用程序时,都会加载上次的任务状态,以便你可以继续之前的上传或下载操作。
封装单例
当我们需要在任意地方方便地进行上传或下载任务的管理时,可以使用单例模式来封装任务管理器,并在该任务管理器中提供方法来处理上传和下载任务。
首先,我们将创建一个名为 TransferManager 的单例类,用于管理上传和下载任务。该类应具有以下功能:
创建单例实例:
定义一个私有的构造函数,防止直接创建实例。
定义一个静态私有变量 _instance 来保存单例实例。
定义一个静态公有方法 getInstance(),用于获取单例实例。
任务管理:
在 TransferManager 类中定义一个私有变量 tasks 来保存所有任务信息。
提供用于添加、移除和获取任务的公有方法,例如 addTask()、removeTask() 和 getTasks()。
上传和下载任务:
在 TransferManager 类中提供公有方法 uploadFile() 和 downloadFile(),用于执行上传和下载任务。
下面是实现以上功能的示例代码:
dart
class TransferManager {
static TransferManager? _instance;
List<TransferTask> tasks = [];
factory TransferManager.getInstance() {
_instance ??= TransferManager._();
return _instance!;
}
TransferManager._();
void addTask(TransferTask task) {
tasks.add(task);
}
void removeTask(TransferTask task) {
tasks.remove(task);
}
List<TransferTask> getTasks() {
return tasks;
}
Future<void> uploadFile(TransferTask task) async {
// 上传文件的逻辑
// ...
}
Future<void> downloadFile(TransferTask task) async {
// 下载文件的逻辑
// ...
}
}
使用 TransferManager 类,你可以在任何地方方便地管理上传和下载任务。首先,通过 TransferManager.getInstance() 获取单例实例,然后就可以使用其提供的方法来添加、移除和获取任务,以及执行上传和下载操作。
例如,在你的应用程序中,可以这样使用:
dart
// 创建单例实例
TransferManager manager = TransferManager.getInstance();
// 添加任务
TransferTask task1 = TransferTask(...);
manager.addTask(task1);
// 获取任务列表
List<TransferTask> tasks = manager.getTasks();
// 执行上传任务
manager.uploadFile(task1);
// 移除任务
manager.removeTask(task1);
// 执行下载任务
manager.downloadFile(task1);
通过封装任务管理器和相关方法,你可以更便捷地管理上传和下载任务,并且可以在任何地方使用同一个单例实例进行任务管理。这样,你就能够更灵活地控制和操作任务,满足不同场景下的需求。
上传model例子
当你调用 downloadFile 方法时,只需要传递一个具有合适属性值的 TransferTask 对象,就可以在方法中使用该对象来执行下载操作。
例如:
dart
TransferTask task = TransferTask(
url: 'https://example.com/file.txt',
destinationPath: '/path/to/save/file.txt',
isPaused: false,
downloadedBytes: 0,
totalBytes: 0,
);
await downloadFile(task);