flutter - 一种通过http提供文件而不将其加载到ram中的方法?帮助。颤振/飞镖
问题描述
因此,我创建了一个使用 httpserver API 创建静态文件服务器的应用程序,并使用 VirtualDirectory 在 Android 上的指定目录中生成项目列表。该应用程序正在运行,但是每当有一个大文件时它就会崩溃,据我所知,这是因为它将太多数据加载到内存中。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'dart:io';
import 'package:http_server/http_server.dart';
import 'package:path_provider/path_provider.dart';
void main(){
runApp(MaterialApp(
home:HomePage(),
));
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
static Future<String> get getFilePath async{
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
static Future<File> getFile(String fileName) async{
final path = await getFilePath;
return File('$path/$fileName');
}
static Future<File> saveToFile(var data, String filePath, String fileName) async{
print("filePath+fileName: " + filePath+fileName);
final file = await getFile(filePath+fileName);
return file.writeAsString(data);
}
static Future<void> createDir(String filePath) async{
final path = await getFilePath;
Directory('$path/$filePath').create(recursive: true);
}
static Future<String> readFromFile(String filePath, String fileName) async{
try{
final file = await getFile('$filePath$fileName');
String fileContents = await file.readAsString();
return fileContents;
}catch(e){
final assetFile = await rootBundle.loadString('assets/$filePath$fileName');
if(filePath == ''){
await saveToFile(assetFile, '$filePath', '$fileName');
}else{
await createDir(filePath);
await saveToFile(assetFile, '$filePath', '$fileName');
}
print('copying the file from assets');
return '';
}
}
String data = '';
String rootDirPathStr;
assetFolder() async{
final v = await getFilePath;
Directory('$v').create(recursive: true);
await createDir('dist/css');
await createDir('dist/js');
await readFromFile('','index.html');
await readFromFile('dist/css','/style.min.css');
await readFromFile('dist/js','/serverCom.js');
await readFromFile('dist/js','/main.js');
await readFromFile('dist/js','/files.js');
await readFromFile('dist/js','/index.json');
}
serverInit() async{
// setState(() {
// data = "Server running on IP : "+server.address.toString()+" On Port : "+server.port.toString();
// });
//getting the dir
final rootDir = await getApplicationDocumentsDirectory();
rootDirPathStr = rootDir.path;
print("rootDirPathStr: " + rootDirPathStr);
//getting the dir
HttpServer server = await HttpServer.bind(InternetAddress.anyIPv4, 8080);
print("Server running on IP : "+InternetAddress.anyIPv4.toString()+" On Port : "+server.port.toString());
VirtualDirectory rootVirDir = VirtualDirectory(rootDirPathStr)
..allowDirectoryListing = true;
VirtualDirectory userFilesVirDir = VirtualDirectory('/storage/emulated/0/IDM/')
..allowDirectoryListing = true;
// await userFilesVirDir.serve(server);
await for (HttpRequest request in server) {
String requestUriPath = request.uri.path;
String requestUriQuery = request.uri.query;
print('requestUriPath: $requestUriPath and requestUriQuery: $requestUriQuery');
if(requestUriPath == '/' && requestUriQuery == '') {
final path = await getFilePath;
await rootVirDir.serveFile(File('$path/index.html'), request);
}else if(requestUriQuery == 'file'){
print('file requested');
try{
await userFilesVirDir.serveRequest(request);
}catch(e){
print("error On file requested: $e");
}
}
else{
await rootVirDir.serveRequest(request);
}
}
}
@override
void initState() {
assetFolder();
serverInit();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child:Text('data'),
),
);
}
}
解决方案
https://pub.dev/packages/shelf可以返回一个 ByteStream 作为响应......允许几乎无限的结果。如https://pub.dev/documentation/shelf/latest/shelf/Response/Response.ok.html中所述:
body 是响应体。它可以是 a
String
、 aList<int>
、 aStream<List<int>>
或null
表示没有主体。
所以你可以在一个大文件上打开一个流,然后直接在响应中传递它(可能通过 StreamTransformer)。我不认为 http_server 可以做到这一点。
推荐阅读
- arrays - 如何获取 REST API JSON 数据并将它们作为表格提取到 Google 电子表格?
- java - 在 Hibernate 5.3 上获取带有 id 的实体列表
- c - C程序输出数组列表,然后在列表之间交换元素并再次输出
- css - 如何在 a 上实现鼠标悬停
- 在 VueJS 中?
- android - 了解可滚动 GridView 中 Cardview 中的解决方法
- spring - Spring mvc web 服务给出 Content-Type →text/html;charset=ISO-8859-1 预期为 [{"key":"Content-Type","value":"application/json"}]
- c++ - C++ DLL 引用来自 C++.exe 的函数和类
- python - 如何连接众多df的熊猫
- swift - Swift 4——尝试使用泛型来减少公式化代码的挑战
- css - 为什么 2 个 div 之间的风格不同?