SoFunction
Updated on 2025-04-13

JavaScript operation method for reading and writing local files

Overview

In pure front-end javaScript, the browser environment does not directly provide the ability to operate the file system. It cannot use the fs module to delete or create files like it does. For the sake of security, web pages are not allowed to access the user's file system at will to prevent potential malicious behavior.

The browser does provide some limited file operation capabilities, mainly through the following methods:

File upload and download:
File upload: can be passed<input type=“file”>Elements let the user select the file and then read the file contents through JavaScript.
File download: Can be createdBlobObjects and usageaTagsdownloadProperties to trigger file download.

File API

File System Access API
File System Access APIIt is a new API introduced by modern browsers (mostly in the Chromium kernel) that allows web pages to interact directly with the user's file system to create, read, write and delete files. This is the closest capability available to the file system operation provided by the current browser.

1: Read the file

(1) The easiest way

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Read the file&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;input type="file" &gt;
&lt;button &gt;Process and Download&lt;/button&gt;
&lt;script&gt;
    ('processButton').addEventListener('click', function () {
        const fileInput = ('fileInput');
        const file = [0];
        if (file) {
            const reader = new FileReader();
             = function (e) {
                // Read file content                let content = ;
                (content);
            };
            // Start reading the file            (file);
        } else {
            alert('Please select a file first!');
        }
    });
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

HTML section:

  • Created a file input box (<input type=“file”>) Let the user select the file.

JavaScript section:

  • A FileReader object is created to read the selected file.
  • useSpecifies what to do when the file is successfully read.
  • use(file)Start reading the file in text.

(II) Read large files

In the above code, the file is read throughFileReaderofreadAsText()The method is completed. This method does load the entire file content into memory at once. This is no problem for small files, but if the file is very large, it can cause excessive memory usage, affect performance, and even cause page crashes.

1. Sharding reading

useFileReaderofreadAsArrayBuffer()Method, then useBlobofslice()Method to read files in chunks.

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Read the file&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;input type="file" &gt;
&lt;button &gt;Process&lt;/button&gt;
&lt;script&gt;
    ('processButton').addEventListener('click', function () {
        const fileInput = ('fileInput');
        const file = [0];
        if (file) {
            const CHUNK_SIZE = 1024 * 1024; // 1MB chunk size            let offset = 0;
            // Functions that recursively read files            function readNextChunk() {
                // Check whether it has been read to the end of the file                if (offset &gt;= ) {
                    ("File processing complete.");
                    return;
                }
                // Read the current block                const chunk = (offset, offset + CHUNK_SIZE);
                const reader = new FileReader();
                 = function (e) {
                    // Process the data of the current block                    let content = ;
                    (`Processing chunk from ${offset} to ${offset + CHUNK_SIZE}`);
                    (content); // More complex processing can be performed here                    // Update the offset and read the next block                    offset += CHUNK_SIZE;
                    readNextChunk();
                };
                 = function (e) {
                    ("Error reading file chunk:", e);
                };
                // Start reading the current block                (chunk);
            }
            // Start reading the first block            readNextChunk();
        } else {
            alert('Please select a file first!');
        }
    });
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

Since file reading is an asynchronous operation, recursively call readNextChunk() to continue with the next block of processing after each block of data is completed.

2. Use stream

Using the File APIstream()Method (supported in newer browsers), which allows you to read files in streaming ways.

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Stream Read File&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;input type="file" &gt;
&lt;button &gt;Process File Stream&lt;/button&gt;
&lt;script&gt;
    ('processButton').addEventListener('click', async function () {
        const fileInput = ('fileInput');
        const file = [0];
        if (file) {
            const stream = ();
            const reader = ();
            // Read stream data            async function read() {
                let result;
                while (!(result = await ()).done) {
                    const chunk = ; // Uint8Array
                    const textChunk = new TextDecoder().decode(chunk); // Convert to text                    (textChunk); // Process data blocks                }
                ("File processing complete.");
            }
            // Start reading            read().catch(error =&gt; ("Stream read error:", error));
        } else {
            alert('Please select a file first!');
        }
    });
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
  • (): This is a new method for the File object, returning aReadableStream, used to read file contents.
  • (): By calling()Get the stream's reader, returnReadableStreamDefaultReaderObject.
  • (): Each time the reader .read() method is called, a block of data is read in the stream and aPromise, the Promise resolves to an object, containingdoneandvalueproperty.

done: If true, it means that the stream has been read.
value: The currently read data block, returned in the form of Uint8Array.

  • TextDecoder: Used toUint8ArrayThe data block is converted into readable text. For non-text data, additional processing can be performed as needed.
  • while loop: bywhileThe loop keeps reading the file stream until the stream ends.
  • passasync/awaitandPromisesImplement concise asynchronous file reading logic.

(III) Attention

1. Security issues

Issue: For security reasons, the browser restricts direct access to the user's file system to prevent malicious scripts from accessing sensitive files or data without the user's consent. The front-end code can only access files through explicitly selected methods for users, such as<input type="file">orFile System Access API

How to deal with it:

User explicit selection: The file selection dialog must be passed (e.g.<input type="file">) Let the user actively select files instead of allowing the script to access directly.

<input type="file" >

File processing permissions: UseFile System Access API(likeshowOpenFilePicker()) When the browser explicitly requests permission from the user. Make sure to request only minimum permissions if necessary.

async function selectFile() {
  const [fileHandle] = await ();
  const file = await ();
  ();
}

Keep permissions minimized: Only request the required files or directories, without attempting to access the entire file system. Limit the scope of operations, such as allowing only reads, avoiding writes or delete operations. 2. Privacy Issues

Problem: User files may contain sensitive information, such as personal data, financial information, etc. When the front-end reads files, it is necessary to ensure that the user's privacy is not leaked or abused.

How to deal with it:

  • Transparency: Clearly inform the user of the content and purpose of the file to be read, avoiding reading data without the user's knowledge.
  • Local processing: Try to process file content locally and avoid uploading data to the server or sending it to third-party services unless the user express consent is obtained.
const reader = new FileReader();
 = function(e) {
  const content = ;
  // Process data only locally};
(file);

Data Cleanup: If you need to transfer file contents to the server, make sure to encrypt sensitive data and clean up unnecessary data after processing.

3. Performance issues

Question: When processing large files on the front end, it may cause excessive memory usage or lag in the browser, affecting the user experience.

How to deal with it:

Block processing: For large files, useFile APIofslice()Method orstream()Methods read files in chunks and process file contents step by step to avoid loading the entire file into memory at once.

const CHUNK_SIZE = 1024 * 1024; // 1MB
let offset = 0;
function readChunk(file) {
  const chunk = (offset, offset + CHUNK_SIZE);
  const reader = new FileReader();
   = function(e) {
    const content = ;
    (content); // Process data blocks    offset += CHUNK_SIZE;
    if (offset &lt; ) {
      readChunk(file); // Continue to read the next block    }
  };
  (chunk);
}

Asynchronous operation: Useasync/awaitorPromisesProcess file reads to avoid blocking the main thread and ensure that the page remains responsive.

4. Compatibility issues

Not all browsers support the latest File System Access API or some advanced file processing features. It is necessary to ensure that the code works properly in multiple browsers, or provide a reasonable fallback mechanism.

Problem: Not all browsers support the latest File System Access API or some advanced file processing features. It is necessary to ensure that the code works properly in multiple browsers, or provide a reasonable fallback mechanism.

How to deal with it:

Feature Detection: Before using certain file APIs, check whether the browser supports this feature. useifStatement checks for a specific API.

if () {
  // Use the File System Access API} else {
  // Fall back to <input type="file">}

5. User experience issues

Problem: Front-end file operations usually involve users selecting files, uploading files, downloading files, etc. A good user experience can improve user satisfaction.

How to deal with it:

Progress Instructions: When processing large files, display a progress indicator (such as a progress bar) to let users understand the progress of file processing and prevent users from feeling that the application is stuck.

&lt;progress  value="0" max="100"&gt;&lt;/progress&gt;	
// Update progress bar when reading file blocks = (offset / ) * 100;

Error handling: Provides friendly error prompts and handling mechanisms to help users understand problems and take action (such as reselecting files).

 = function(e) {
  alert('Error reading file: ' + );
};

Feedback and confirmation: When the file operation is successfully completed, give feedback to the user, such as prompting the file to be processed or confirming that the download has been completed.

6. Permission management issues

Issue: File operations may involve permission issues, such as permissions may be revoked when accessing a file system through the File System Access API.

How to deal with it:

Permission Check: Before each operation, check whether you still have permission to access files or directories. If the permission is revoked, the user is prompted to reauthorize.

const permission = await ();
if (permission !== 'granted') {
  // Prompt the user to re-authorize}

Permission request: If there is no permission, you can use the requestPermission() method to actively request permissions.

const permission = await ();
if (permission === 'granted') {
  // Perform file operations}

7. File type and content verification

Problem: Users may select a file of the wrong type, or upload a file containing malicious content.

How to deal with it:

File Type Filtering: Use<input type="file">ElementalacceptAttributes limit the file type selected by the user. For example, restrict only .txt files are selected.

<input type="file" accept=".txt">

Content Verification: Verify the actual content format of the file before processing the file content. For example, if the file is in JSON format, you can try to parse the content and catch the error.

try {
  const data = (fileContent);
} catch (e) {
  alert('Invalid JSON format');
}

8. File size limit

Problem: Handling very large files can cause memory overflow or performance issues.

How to deal with it:

Limit file size: Set file size limits in front-end code and check when the user selects a file. If the file is too large, give a prompt.

const MAX_SIZE = 10 * 1024 * 1024; // 10MB
if ( > MAX_SIZE) {
  alert('File is too large!');
  return;
}

Here is an example 🌰:

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;File processing&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;input type="file"  accept=".pdf"&gt;
&lt;button &gt;Process&lt;/button&gt;
&lt;progress  value="0" max="100" style="display: none;"&gt;&lt;/progress&gt;
&lt;p &gt;0%&lt;/p&gt;
&lt;p &gt;&lt;/p&gt;
&lt;script&gt;
    ('processButton').addEventListener('click', function () {
        const fileInput = ('fileInput');
        const file = [0];
        const MAX_SIZE = 300 * 1024 * 1024; // Maximum 300MB        const progressBar = ('progressBar');
        const percentageDisplay = ('percentage');
        const statusMessage = ('statusMessage');
        // Reset status         = 'none';
         = 0;
         = '0%';
         = '';
        // Check whether the file is selected        if (!file) {
            alert('Please select a file first!');
            return;
        }
        // Check file size        if ( &gt; MAX_SIZE) {
            alert('File is too large! Please select a file under 300MB.');
            return;
        }
        (`Selected file: ${}, ${} bytes, ${}`);
        // // Check file type (assuming only text files are accepted)        // if ( !== "text/plain") {
        //     alert('Invalid file type! Please select a .pdf file.');
        //     return;
        // }
        const CHUNK_SIZE = 1024 * 1024; // 1MB chunk size        let offset = 0;
        // Show progress bar         = 'block';
        // Functions that recursively read files        function readNextChunk() {
            // Check whether it has been read to the end of the file            if (offset &gt;= ) {
                 = "File processing complete.";
                 = 'none';
                return;
            }
            // Read the current block            const chunk = (offset, offset + CHUNK_SIZE);
            const reader = new FileReader();
             = function (e) {
                // Process the data of the current block                let content = ;
                (`Processing chunk from ${offset} to ${offset + CHUNK_SIZE}`);
                (content); // More complex processing can be performed here                // Update the offset and read the next block                offset += CHUNK_SIZE;
                // Calculate the percentage and update the display                const percentage = ((offset / ) * 100, 100).toFixed(2);
                 = percentage;
                 = `${percentage}%`;
                readNextChunk();
            };
             = function (e) {
                ("Error reading file chunk:", e);
                 = "Error reading file!";
                 = 'none';
            };
            // Start reading the current block            (chunk);
        }
        // Start reading the first block        readNextChunk();
    });
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

2. Write a document

Writing information to local files in front-end code is a common requirement, but due to browser security limitations, this process is not as direct as it is on the back-end. We have several ways to implement this function, each with its advantages and disadvantages.

(I) The most commonly used method

The most commonly used method is usedBloband()

function saveToFile(content, filename) {
    const blob = new Blob([content], { type: 'text/plain' });
    const url = (blob);
    const link = ('a');
     = url;
     = filename;    
    // This line is necessary to trigger downloads in the browser    (link);    
    ();    
    // Clean and remove links    (link);
    (url);
}
// Use examplesaveToFile('Hello, World!', '');

advantage:

  • Widely supported, suitable for most modern browsers.
  • Can handle large files.
  • All kinds of data can be saved (not just text).

shortcoming:

  • The user needs to select a save location and cannot directly write to a specific location.
  • You cannot append content to existing files.

(II) Use the File System Access API

This is a newer API that provides more powerful file manipulation capabilities, but currently only supports it in some modern browsers.

async function writeToFile(content) {
    if ('showSaveFilePicker' in window) {
        try {
            const handle = await ({
                types: [{
                    description: 'Text file',
                    accept: { 'text/plain': ['.txt'] },
                }],
            });
            const writable = await ();
            await (content);
            await ();
            ('File saved successfully');
        } catch (err) {
            ('Error saving file:', err);
        }
    } else {
        ('File System Access API not supported');
    }
}
// Use examplewriteToFile('Hello, World!');

advantage:

  • Provides more powerful file operation capabilities, including reading, writing and modifying files.
  • You can access the file or directory selected by the user.
  • Supports large files and streaming operations.

shortcoming:

  • Browser support is limited, mainly new versions of Chrome and Edge.
  • Users need to explicitly grant permissions.

(III) Use LocalStorage or IndexedDB

Instead of saving the data directly as a file, these methods store the data in the browser's local storage.

For LocalStorage:

function saveToLocalStorage(key, value) {
    (key, value);
}
// Use examplesaveToLocalStorage('myData', 'Hello, World!');

For IndexedDB, the code will be relatively complex, here is a simplified example:

let db;
const dbName = "MyDatabase";
const request = (dbName, 1);
 = function(event) {
    ("Database error: " + );
};
 = function(event) {
    db = ;
    ("Database opened successfully");
};
 = function(event) {
    db = ;
    const objectStore = ("files", { keyPath: "id" });
};
function saveToIndexedDB(id, content) {
    const transaction = (["files"], "readwrite");
    const objectStore = ("files");
    const request = ({ id: id, content: content });  
     = function(event) {
        ("Error saving data: " + );
    };    
     = function(event) {
        ("Data saved successfully");
    };
}
// Use example (need to be called after the database is opened)saveToIndexedDB('file1', 'Hello, World!');

advantage:

  • Data can be saved without user interaction.
  • Data persistence is stored in the browser.
  • Suitable for storing application status or small datasets.

shortcoming:

  • Storage capacity is limited (LocalStorage is usually limited to about 5MB).
  • Data is stored only in the browser, not a real file.
  • The user will lose when clearing the browser data.

A complete example 🌰:

&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;File saving example&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        textarea {
            width: 100%;
            height: 100px;
            margin-bottom: 10px;
        }
        button {
            margin-right: 10px;
            margin-bottom: 10px;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;File saving example&lt;/h1&gt;
&lt;textarea  placeholder="Enter what you want to save here"&gt;&lt;/textarea&gt;
&lt;div&gt;
    &lt;button onclick="saveUsingBlob()"&gt;useBlobdownload&lt;/button&gt;
    &lt;button onclick="saveUsingFileSystem()"&gt;useFile System APIsave&lt;/button&gt;
    &lt;button onclick="saveToLocalStorage()"&gt;save到LocalStorage&lt;/button&gt;
    &lt;button onclick="saveToIndexedDB()"&gt;save到IndexedDB&lt;/button&gt;
&lt;/div&gt;
&lt;div &gt;&lt;/div&gt;
&lt;script&gt;
    // Use Blob and () methods    function saveUsingBlob() {
        const content = ('content').value;
        const blob = new Blob([content], {type: 'text/plain'});
        const url = (blob);
        const link = ('a');
         = url;
         = '';
        (link);
        ();
        (link);
        (url);
        updateStatus('The file is ready to download');
    }
    // Use File System Access API    async function saveUsingFileSystem() {
        const content = ('content').value;
        if ('showSaveFilePicker' in window) {
            try {
                const handle = await ({
                    types: [{
                        description: 'Text file',
                        accept: {'text/plain': ['.txt']},
                    }],
                });
                const writable = await ();
                await (content);
                await ();
                updateStatus('File saved successfully');
            } catch (err) {
                updateStatus('An error occurred while saving the file: ' + err);
            }
        } else {
            updateStatus('This browser does not support the File System Access API');
        }
    }
    // Use LocalStorage    function saveToLocalStorage() {
        const content = ('content').value;
        try {
            ('savedContent', content);
            updateStatus('Content saved to LocalStorage');
        } catch (err) {
            updateStatus('An error occurred while saving to LocalStorage: ' + err);
        }
    }
    // Use IndexedDB    let db;
    const dbName = "MyDatabase";
    const dbVersion = 1;
    const request = (dbName, dbVersion);     = function (event) {
        updateStatus("An error occurred while opening the database: " + );
    };
     = function (event) {
        db = ;
        updateStatus("The database has been opened successfully");
    };
     = function (event) {
        db = ;
        const objectStore = ("files", {keyPath: "id"});
        updateStatus("Database created");
    };
    function saveToIndexedDB() {
        const content = ('content').value;
        if (!db) {
            updateStatus("The database is not ready");
            return;
        }
        const transaction = (["files"], "readwrite");
        const objectStore = ("files");
        const request = ({id: "file1", content: content});
         = function (event) {
            updateStatus("An error occurred while saving to IndexedDB: " + );
        };
         = function (event) {
            updateStatus("Content has been saved to IndexedDB successfully");
        };
    }
    function updateStatus(message) {
        ('status').textContent = message;
    }
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

I will also record it, so it will be convenient for future use. Attach the original address and respect the original!

This is the article about JavaScript reading and writing local files. For more related JavaScript reading and writing local files, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!