You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web大文件上传时出现Array buffer分配失败如何解决?

错误原因

你遇到的RangeError: Array buffer allocation failed错误是Flutter Web环境下全量加载大文件到内存导致的:

  • 虽然你给pickFiles开启了withReadStream: true拿到了文件流,但Dart官方http库的MultipartFile在Web端实现时,会提前把整个文件流的内容全部读取到内存的Uint8List中,再生成请求体
  • 当上传的文件过大(通常超过500MB,具体阈值取决于浏览器内存限制)时,浏览器无法分配足够大的连续数组缓冲区存储整个文件内容,就会抛出这个错误。

解决方案

  • 方案1:基于浏览器原生API实现流式上传(适合GB级以内文件)

    直接调用Web原生的FormData和HttpRequest能力,不会把整个文件加载到内存,浏览器会自动处理流式上传:

    import 'dart:html' as html;
    import 'package:file_picker/file_picker.dart';
    
    // 选完文件后获取原生File对象
    List<PlatformFile>? files = fileUploadView.result?.files;
    if (files == null || files.isEmpty) return;
    
    // 创建原生FormData
    final formData = html.FormData();
    for (var file in files) {
      // Web端PlatformFile的path属性对应原生File对象
      html.File nativeFile = file.path as html.File;
      formData.appendBlob(
        "你的服务端接收参数名", 
        nativeFile, 
        file.name
      );
    }
    
    // 发送请求
    final request = html.HttpRequest();
    request.open('POST', '你的上传接口地址');
    // 按需添加请求头,比如鉴权token
    request.setRequestHeader('Authorization', 'Bearer your_token');
    request.onLoadEnd.listen((_) {
      if (request.status == 200) {
        // 上传成功逻辑
        print('上传成功: ${request.responseText}');
      } else {
        // 上传失败逻辑
        print('上传失败: ${request.status}');
      }
    });
    // 监听上传进度(可选)
    request.upload.onProgress.listen((event) {
      if (event.lengthComputable) {
        double progress = event.loaded! / event.total!;
        print('上传进度: ${(progress * 100).toStringAsFixed(2)}%');
      }
    });
    request.send(formData);
    
  • 方案2:分片上传(适合超过2GB的超大文件,支持断点续传)

    超过浏览器单次上传大小限制的文件,需要切割成分片逐个上传,后端需要配套支持分片合并、断点校验逻辑:
    核心实现逻辑:

    1. 按固定分片大小(通常5MB~20MB)调用原生File.slice方法切割文件
    2. 每个分片携带文件唯一标识、分片序号、总分片数参数上传
    3. 所有分片上传完成后调用后端接口合并分片
      分片核心代码示例:
    const int chunkSize = 10 * 1024 * 1024; // 10MB每片
    html.File nativeFile = file.path as html.File;
    int totalChunks = (nativeFile.size / chunkSize).ceil();
    String fileId = '生成文件唯一标识,比如文件hash+文件名';
    
    for (int i = 0; i < totalChunks; i++) {
      final start = i * chunkSize;
      final end = start + chunkSize > nativeFile.size ? nativeFile.size : start + chunkSize;
      final chunk = nativeFile.slice(start, end);
      
      final chunkFormData = html.FormData();
      chunkFormData.appendBlob('chunk', chunk, '${fileId}_$i');
      chunkFormData.append('fileId', fileId);
      chunkFormData.append('chunkIndex', i.toString());
      chunkFormData.append('totalChunks', totalChunks.toString());
      
      // 发送当前分片请求,可自行添加失败重试、并发控制逻辑
      // ...
    }
    // 所有分片上传完成后调用合并接口
    

内容的提问来源于stack exchange,提问作者EinEsellesEniE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:15:04