簡體   English   中英

如何在 flutter 中的 memory 中寫入或保存大文件

[英]How to Write or save Large files in memory in flutter

我目前面臨一個問題,我正在嘗試保存一個大視頻文件 (586 Mb)。 我可以下載整個文件,但是當我嘗試將此文件寫入 memory 時,我收到“內存不足”錯誤。 它適用於較小的視頻文件,如(80mb,100mb),但不適用於大文件。 我附上代碼片段以供參考。

Future download() async {
var request = http.Request('GET', Uri.parse(url!));
var response = httpClient.send(request).timeout(Duration(seconds: 3));

var chunks = <List<int>>[];
var downloaded = 0;
try{
  response.asStream().listen((http.StreamedResponse r) {
    if(r.statusCode==HttpStatus.ok){
      r.stream.listen((List<int> chunk) {
        // Display percentage of completion
        chunks.add(chunk);
        downloaded += chunk.length;
        downloadingCallBack(downloaded / r.contentLength! * 100,filesize(downloaded),filesize(r.contentLength));
      }, onDone: () async {
        // Display percentage of completion
        print('downloadPercentage: ${downloaded / r.contentLength! * 100}');
        // Save the file
        try{
          var file =  File('$dirPath/$fileName');
          //The Uint8List below throws the error "Out of memory and I'm not able to write the file to memory" 
         ***Error Here ==>*** final bytes = Uint8List(r.contentLength!); //Code fails here, (r.contentLength is 586900112 bytes)
          var offset = 0;
          for (var chunk in chunks) {
            bytes.setRange(offset, offset + chunk.length, chunk);
            offset += chunk.length;
          }
          await file.writeAsBytes(bytes);
          downloadingDoneBack(true);
          return;
        }catch(fileException){
          rethrow;
        }finally{
          httpClient.close();
        }

      });
    }else{
      downloadingDoneBack(false);
    }

  });
}catch(e){
  downloadingDoneBack(false);
}finally{
  httpClient.close();
}

}

由於它是一個大文件,我認為最好使用也支持通知和后台模式的flutter_downloader插件下載文件。

導入並初始化flutter下載器

import 'package:flutter_downloader/flutter_downloader.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Plugin must be initialized before using
  await FlutterDownloader.initialize(
    debug: true // optional: set to false to disable printing logs to console (default: true)
    ignoreSsl: true // option: set to false to disable working with http links (default: false)
  );

  runApp(const MyApp())
}

創建新的下載任務

final taskId = await FlutterDownloader.enqueue(
  url: 'your download link',
  savedDir: 'the path of directory where you want to save downloaded files',
  showNotification: true, // show download progress in status bar (for Android)
  openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);

處理隔離物

重要提示:您的 UI 在主隔離中呈現,而下載事件來自后台隔離(換句話說,回調中的代碼在后台隔離中運行),因此您必須處理兩個隔離之間的通信。 例如:

ReceivePort _port = ReceivePort();

@override
void initState() {
  super.initState();

  IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
  _port.listen((dynamic data) {
    String id = data[0];
    DownloadTaskStatus status = data[1];
    int progress = data[2];
    setState((){ });
  });

  FlutterDownloader.registerCallback(downloadCallback);
}

@override
void dispose() {
  IsolateNameServer.removePortNameMapping('downloader_send_port');
  super.dispose();
}

static void downloadCallback(String id, DownloadTaskStatus status, int progress) {
  final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port');
  send.send([id, status, progress]);
}

加載所有下載任務

final tasks = await FlutterDownloader.loadTasks();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM