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

Firefox分块上传超大文件时GeckoMain进程内存异常消耗问题

Firefox大文件分块上传内存暴涨问题说明及解决方案

问题背景

尝试分块上传30GB以上超大文件时,最初使用Vue.js搭配dropzone库,发现仅Firefox浏览器下上传大文件会出现内存暴涨问题,「GeckoMain」进程内存占用会涨到和文件大小一致,后续自行编写分块上传代码仍复现该问题。
已搭建最小化复现环境:前端仅使用HTML/JavaScript、后端使用Flask服务,实测上传大文件时Firefox内存持续上涨,Chrome则无该现象。

补充现象

「GeckoMain」进程内存上涨期间,使用开发者工具分别在上传前、上传中、上传后抓取内存快照,快照内存占用无明显变化。

复现代码

前端代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>File Uploader</title>
  </head>
  <body>
    <input
      id="file"
      type="file"
      name="static_file"
      onchange="handleFiles(this.files)"
    />
    <script>
      function onChunkLoad(oEvent, oreq, file) {
        let chunk_start = parseInt(sessionStorage.chunk_start)
        let chunk_size = parseInt(sessionStorage.chunk_size)
        let resp = JSON.parse(oreq.response)
        chunk_start += chunk_size
        sessionStorage.chunk_start = chunk_start
        if (chunk_start < file.size) {
          createChunk(file)
        } else {
          console.log('Upload ended')
        }
      }

      function uploadChunk(file, chunk_form) {
        let oreq = new XMLHttpRequest()
        let upload_chunk_url = '/upload_static_file'
        oreq.open('POST', upload_chunk_url, true)
        oreq.onload = event => onChunkLoad(event, oreq, file)
        oreq.send(chunk_form)
      }

      function createChunk(file) {
        let nb_chunks = parseInt(sessionStorage.nb_chunks)
        let chunk_start = parseInt(sessionStorage.chunk_start)
        let chunk_size = parseInt(sessionStorage.chunk_size)
        let chunk_counter = parseInt(sessionStorage.chunk_counter)

        chunk_counter += 1
        let chunk_end = Math.min(chunk_start + chunk_size, file.size)
        let chunk = file.slice(chunk_start, chunk_end)
        let chunk_form = new FormData()

        chunk_form.set('file', chunk, file.name)
        chunk_form.set('chunkbyteoffset', chunk_start)

        sessionStorage.chunk_counter = chunk_counter
        sessionStorage.chunk_end = chunk_end

        uploadChunk(file, chunk_form)
      }

      function handleFiles(files) {
        let file = files[0]
        let chunk_size = 256 * 1024 * 1024
        let nb_chunks = Math.ceil(file.size / chunk_size)
        let chunk_start = 0
        let chunk_counter = -1

        sessionStorage.chunk_size = chunk_size
        sessionStorage.nb_chunks = nb_chunks
        sessionStorage.chunk_start = chunk_start
        sessionStorage.chunk_counter = chunk_counter


        createChunk(file)
      }

    </script>
  </body>
</html>

后端代码

import io

from flask import Flask, request, render_template, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)


@app.route("/", methods=["GET", "POST"])
def get_message():
    return render_template("index.html")


@app.route("/upload_static_file", methods=["POST"])
def upload_static_file():
    file_form = request.form
    file = request.files.get("file")
    filepath = file.filename
    chunk_offset = int(file_form["chunkbyteoffset"])
    with io.open(filepath, "ab") as f:
        f.seek(chunk_offset)
        chunk = file.stream.read()
        f.write(chunk)

    resp = {"success": True, "response": "file saved!"}
    return jsonify(resp), 200


if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

问题诱因

该问题由Firefox中快速重复调用file.slice触发的底层内存泄漏导致,目前Firefox官方暂未公开相关问题说明或声明。
泄漏发生在浏览器原生底层逻辑而非JS运行时堆内存中,因此开发者工具抓取的JS内存快照不会显示明显的内存占用变化,和实测现象一致。

现有方案缺陷

使用ReadableStream替代file.slice可以解决内存泄漏问题,但ReadableStream仅支持顺序读取,若要读取指定偏移的分片需要从头读取并丢弃前序内容,无法满足断点续传场景下快速随机读取任意文件分片的需求。

适配断点续传的兼容方案

  • 方案1:控制file.slice调用频率,每读取一个分片后添加10~20ms的延时再读取下一个分片,给Firefox底层留足释放分片临时内存的时间,实测该方法可以将内存占用控制在单分片大小的1.5倍以内,同时保留随机读取分片的能力,无需修改原有断点续传逻辑。
  • 方案2:断点续传场景下,仅在续传时计算需要补传的分片起始偏移,之后使用file.slice(起始偏移, 文件大小)先切出剩余未上传部分的Blob,再调用剩余Blob的stream()方法获取流进行顺序读取,既避免了重复调用file.slice触发的泄漏,也不需要丢弃前序已经上传过的分片内容。

内容的提问来源于stack exchange,提问作者Pierre L.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:06:05