local_server.dart
4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import 'dart:io';
import 'package:archive/archive.dart';
import 'package:flutter/services.dart';
late HttpServer localServer;
Future<void> startLocalServer() async {
HttpServer localServer = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
print('本地服务器启动在端口: ${localServer.port}');
localServer.listen((HttpRequest request) async {
final String requestPath = request.uri.path == '/' ? '/index.html' : request.uri.path;
try {
if (requestPath.startsWith('/temp/')) {
// 临时目录文件的请求
await _serveTempFile(request, requestPath);
} else if (requestPath.startsWith('/test/')) {
// assets文件服务逻辑
await _serveAssetFile(request, requestPath);
} else {
// asset/dist.zip 文件服务逻辑
await _serveZipFileContent(request, requestPath);
}
} catch (e) {
print('处理请求时出错: $e');
request.response
..statusCode = HttpStatus.internalServerError
..write('Internal server error')
..close();
}
});
}
// 临时目录的文件
Future<void> _serveTempFile(HttpRequest request, String requestPath) async {
try {
// 临时文件已经设备路径
// 构建文件路径(移除 /temp 前缀)
final String filePath = requestPath.substring('/temp/'.length);
// 检查文件是否存在
final File file = File(filePath);
if (await file.exists()) {
// 读取文件内容
final List<int> bytes = await file.readAsBytes();
request.response
..headers.contentType = ContentType.parse(_getContentType(filePath))
..add(bytes)
..close();
} else {
request.response
..statusCode = HttpStatus.notFound
..write('File not found: $filePath')
..close();
}
} catch (e) {
print('读取临时文件时出错: $e');
request.response
..statusCode = HttpStatus.notFound
..write('File not found')
..close();
}
}
Future<void> _serveZipFileContent(HttpRequest request, String requestPath) async {
String zipAssetPath = 'assets/dist.zip';
try {
// 使用 rootBundle.load 加载资源文件
final ByteData data = await rootBundle.load(zipAssetPath);
final List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// 读取并解压zip文件内容
final Archive archive = ZipDecoder().decodeBytes(bytes);
// 查找请求的内部文件
ArchiveFile? targetFile;
for (final file in archive) {
// 标准化路径分隔符(统一使用 '/')
String zipFileName = file.name.replaceAll('\\', '/');
// 移除开头的 '/'(如果存在)
if (requestPath.startsWith('/')) {
requestPath = requestPath.substring(1);
}
if (zipFileName == requestPath) {
targetFile = file;
break;
}
}
if (targetFile == null) {
request.response
..statusCode = HttpStatus.notFound
..write('File not found in zip: $requestPath')
..close();
return;
}
// 返回文件内容
request.response
..headers.contentType = ContentType.parse(_getContentType(requestPath))
..add(targetFile.content as List<int>)
..close();
} catch (e) {
print('读取zip文件时出错: $e');
request.response
..statusCode = HttpStatus.internalServerError
..write('Error reading zip file')
..close();
}
}
// 访问assets目录下的文件
Future<void> _serveAssetFile(HttpRequest request, String requestPath) async {
// 构建文件路径(移除 /test 前缀)
final String path = requestPath.substring('/test'.length);
final String filePath = 'assets$path';
try {
final ByteData data = await rootBundle.load(filePath);
final List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
request.response
..headers.contentType = ContentType.parse(_getContentType(filePath))
..add(bytes)
..close();
} catch (e) {
request.response
..statusCode = HttpStatus.notFound
..write('File not found: $filePath')
..close();
}
}
String _getContentType(String filePath) {
if (filePath.endsWith('.html')) return 'text/html';
if (filePath.endsWith('.js')) return 'application/javascript';
if (filePath.endsWith('.css')) return 'text/css';
if (filePath.endsWith('.png')) return 'image/png';
if (filePath.endsWith('.jpg') || filePath.endsWith('.jpeg')) return 'image/jpeg';
return 'application/octet-stream';
}