Start now →

JavaScript: Working with Large Files in the Browser. Creating 5GB Files in the Browser

By Alexey Boyko · Published June 8, 2026 · 4 min read · Source: Level Up Coding
DeFi
JavaScript: Working with Large Files in the Browser. Creating 5GB Files in the Browser

Online board DGRM.net caches files in a persistent cache. The persistent cache isn’t deleted when you close a tab. I’ll explain how to store large files in your browser.

Fig. 1. Memory consumption when a file is fully loaded into memory
Figure 1. Memory consumption when a file is fully loaded into memory

File cache on origin private file system (OPFS)

A persistent file cache can be created using the cache API, indexedDB, or OPFS. OPFS is considered the fastest. OPFS is a virtual file system. You can create files and folders. Other websites will not have access to your files.

Writing files to OPFS

You can get a link to a file on the user’s device using HTMLInputElement. This will prevent the file data from being loaded into memory.

/**
* @param {string} [accept]
* @returns {Promise<File>}
*/
const fileInputOpen = accept => new Promise((resolve, reject) => {
const input = document.createElement('input');
input.type = 'file';
input.multiple = false;
input.accept = accept;
input.style.display = 'none';
document.body.appendChild(input);

const dispose = () => input?.remove();

input.oncancel = () => {
resolve(null);
dispose();
};
input.onchange = () => {
resolve((!input.files?.length) ? null : input.files[0]);
dispose();
};

input.click();
});

Listing 1. Getting a link to a file

Writing a file to OPFS — Listing 2.

/**
* @param {string} fileName
* @param {Blob} blob
*/
const fileAdd = async (fileName, blob) => {
const dir = await navigator.storage.getDirectory();

const writable =
await (await dir.getFileHandle(fileName, { create: true }))
.createWritable();

// (1) FireFox will load all file into memory
// Chrome drop exception
// await writable.write(await blob.bytes());

// (2) very slow in FireFox
// await writable.write(blob);

// (3) works in Chrome and FireFox.
// In Chrome slower then (2)
await blob.stream().pipeTo(writable, { preventClose: true });

await writable.close();
};

Listing 2. Writing a file to OPFS

Listing 2 shows three file copy options in OPFS. I tested this on a 5 GB file on Windows 11 and Ubuntu.

Option (1) blob.bytes()

Option (1) shows loading the entire file into memory. RAM consumption is clearly visible (Figure 2). Firefox on Windows will load the entire file into memory, while on Ubuntu it will load 2 GB into memory and throw an exception. Chrome will throw an exception.

Fig. 2. FireFox (1) file.bytes(). Memory consumption when loading a file into memory.
Figure 2. FireFox (1) file.bytes(). Memory consumption when loading a file into memory.

Option (2) writable.write(blob)

(2) Works quickly in Chrome — 23 seconds. In Firefox, it’s very slow — over a minute. The file isn’t loaded into memory entirely, but is copied in chunks — see Figures 3 and 4. The graphs are similar in Chrome and Firefox, only the time in Firefox is stretched.

Figure 3. Chrome (2) writable.write(file). Memory usage
Figure 3. Chrome (2) writable.write(file). Memory usage
Figure 4. Chrome (2) wr.writable(file). Disk accesses
Figure 4. Chrome (2) wr.writable(file). Disk accesses

Option (3) blob.stream().pipeTo(writable)

Works well in Chrome and Firefox. In Chrome, it’s slower than (2). The graphs are similar to (2). Option (3) with pipeTo turned out to be better (Table 1).

Table 1. Comparison of file creation methods in OPFS
Table 1. Comparison of file creation methods in OPFS

Writing a portion of a file to OPFS

To write a portion of a file to OPFS, use blob.slice(). Listing 3 — writing a portion of a file to OPFS without loading the entire file into memory.

const file = await fileInputOpen(); 
if (!file) { return; }

await fileAdd(
file.name,
// upload second byte
file.slice(1, 2));

Listing 3. Writing part of a file to OPFS without loading the entire file into memory

For information on how to store a lot of different data in one large file, see the first part of the article.

Reading from OPFS

A file from OPFS can be output to an image, <audio>, <video> — listing 4.

const img =
/** @type {HTMLImageElement} */(document.getElementById('img'));

const dir = await navigator.storage.getDirectory();
img.src = URL.createObjectURL(
await (await dir.getFileHandle('1.png')).getFile()
);

// don't forget to revoke object url when delete img
// URL.revokeObjectURL(img.src)

Listing 4. Displaying an image from OPFS

Downloading a file from OPFS — Listing 5.

/**
* @param {Blob} blob
* @param {string} name
*/
const fileDownload = (blob, name) => {
const link = document.createElement('a');
link.download = name;
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
link.remove();
};

//
// usage

const dir = await navigator.storage.getDirectory();
fileDownload(
await (await dir.getFileHandle('big.zip')).getFile(),
'big.zip'
);

Listing 5. Downloading a file from OPFS

Google claims you can download files up to 1 GB this way. In reality, 5 GB downloads are no problem in Chrome and Firefox on Windows and Ubuntu. RAM consumption doesn’t increase.

Creating files on the user’s device

Chrome can write files directly to the user’s file system. Writing to a file can be done in chunks; the API is the same as in OPFS — Listing 6.

if (window['showSaveFilePicker']) {
/** @type {FileSystemFileHandle} */
const file =
// @ts-ignore
await window.showSaveFilePicker({
suggestedName: 'my.png' });

const writable = await file.createWritable();

// write your data
// await blob1.stream().pipeTo(writable, { preventClose: true });
// await blob2.stream().pipeTo(writable, { preventClose: true });

await writable.close();
}

Listing 6. Creating a file on the user’s device

In other browsers, you will have to create a temporary file in OPFS and download it using a link — see Listing 5.

Self-promotion

Recently added to DGRM.net audio and video. I use it for guitar lessons — it’s convenient. Give it a try.


JavaScript: Working with Large Files in the Browser. Creating 5GB Files in the Browser was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.

This article was originally published on Level Up Coding and is republished here under RSS syndication for informational purposes. All rights and intellectual property remain with the original author. If you are the author and wish to have this article removed, please contact us at [email protected].

NexaPay — Accept Card Payments, Receive Crypto

No KYC · Instant Settlement · Visa, Mastercard, Apple Pay, Google Pay

Get Started →