首页 > 解决方案 > 一种通过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'),
      ),
    );
  }
}

标签: flutterhttpdartserverram

解决方案


https://pub.dev/packages/shelf可以返回一个 ByteStream 作为响应......允许几乎无限的结果。如https://pub.dev/documentation/shelf/latest/shelf/Response/Response.ok.html中所述:

body 是响应体。它可以是 a String、 a List<int>、 aStream<List<int>>null表示没有主体。

所以你可以在一个大文件上打开一个流,然后直接在响应中传递它(可能通过 StreamTransformer)。我不认为 http_server 可以做到这一点。


推荐阅读