浏览器和 node 操作文件的 api 以及区别
核心区别:环境与权限
- 浏览器:运行在沙盒环境中,无权直接访问用户文件系统。文件操作必须由用户主动触发(如通过
<input type="file">
选择文件),并且通常是只读的(新标准允许写入,但有特定限制)。 - Node.js:作为服务端运行时,拥有直接的文件系统访问权限。可以自由地进行文件的读、写、删除、监听等所有操作。
下面我们分别来看它们的 API 生态。
一、浏览器 (Web) 文件操作 API
浏览器端的文件操作主要围绕 用户手动选择的文件(File对象) 或 从服务器获取的二进制数据。
1. 获取文件 (Acquiring Files)
<input type="file">
:最传统的方式,用户通过选择对话框选择一个或多个文件。<input type="file" id="file-input" multiple> <script>document.getElementById('file-input').addEventListener('change', (event) => {const fileList = event.target.files; // FileList 对象const firstFile = fileList[0]; // File 对象}); </script>
- 拖放 API (Drag and Drop API):用户将文件拖拽到浏览器指定区域。
const dropZone = document.getElementById('drop-zone'); dropZone.addEventListener('drop', (event) => {event.preventDefault();const files = event.dataTransfer.files; // 同样得到 FileList });
- File System Access API (现代API):允许更直接地访问文件,用户授权后甚至可以保存修改。
// 显示文件选择器,获取一个 File 对象 const [fileHandle] = await window.showOpenFilePicker(); const file = await fileHandle.getFile();
2. 读取文件内容 (Reading File Content)
获取到 File
对象(它是 Blob
的子类)后,需要读取其内容。
FileReader
:传统且最常用的异步文件读取器。const reader = new FileReader(); const file = ... // 来自 input 或 drag & drop// 启动读取 reader.readAsText(file); // 读取为文本 // reader.readAsArrayBuffer(file); // 读取为 ArrayBuffer (二进制) // reader.readAsDataURL(file); // 读取为 Data URL (base64)// 监听读取完成事件 reader.onload = (event) => {const content = event.target.result; // 读取的结果console.log(content); };
Blob.arrayBuffer()
/Blob.text()
:更现代、基于 Promise 的读取方式,代码更简洁。const file = ... // 一个 File 对象// 读取为文本 const text = await file.text(); console.log(text);// 读取为 ArrayBuffer (二进制) const arrayBuffer = await file.arrayBuffer(); console.log(arrayBuffer);
3. 写入文件 (Writing Files - 非常有限)
- 下载方式:通过创建
Blob
和URL
触发浏览器下载。function downloadContent(content, fileName, contentType) {const blob = new Blob([content], { type: contentType });const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = fileName;a.click();URL.revokeObjectURL(url); } // 使用:downloadContent('Hello world!', 'hello.txt', 'text/plain');
- File System Access API:允许在用户明确授权的情况下,将内容写回原文件。
// 获取文件句柄并写入 const fileHandle = await window.showSaveFilePicker(); const writableStream = await fileHandle.createWritable(); await writableStream.write('Hello World'); await writableStream.close();
二、Node.js 文件操作 API
Node.js 通过内置的 fs
(file system) 模块 提供完整的文件 I/O 能力。
1. 核心 API 风格:回调 vs Promise
fs
模块为几乎所有操作都提供了三种风格:
- 同步 (Synchronous):阻塞事件循环,直到操作完成。方法名带
Sync
。 - 回调 (Callback):传统的异步方式,通过回调函数返回错误或结果。
- Promise:现代的异步方式,返回 Promise 对象。需要从
fs/promises
导入。
2. 读取文件 (Reading Files)
// 方式一:回调函数式 (require('fs'))
const fs = require('fs');
fs.readFile('/path/to/file.txt', 'utf8', (err, data) => {if (err) throw err;console.log(data); // 文件内容
});// 方式二:Promise式 (import from 'fs/promises')
const fs = require('fs/promises');
async function readFile() {try {const data = await fs.readFile('/path/to/file.txt', 'utf8');console.log(data);} catch (err) {console.error(err);}
}
readFile();// 方式三:同步式
const data = fs.readFileSync('/path/to/file.txt', 'utf8');
console.log(data);
3. 写入文件 (Writing Files)
const fs = require('fs/promises');async function writeFile() {try {// 写入文本await fs.writeFile('/path/to/file.txt', 'Hello Node.js!', 'utf8');// 写入 Buffer (二进制)const buf = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]);await fs.writeFile('/path/to/file.bin', buf);} catch (err) {console.error(err);}
}
writeFile();
4. 其他常用操作
Node.js fs
模块的功能远不止读写:
fs.appendFile()
:追加内容到文件末尾。fs.unlink()
:删除文件。fs.readdir()
:读取目录内容。fs.mkdir()
/fs.rmdir()
:创建/删除目录。fs.stat()
/fs.access()
:获取文件信息/检查权限。fs.watch()
:监听文件或目录的变化。fs.createReadStream()
/fs.createWriteStream()
:处理大文件的流式读写,高效且节省内存。
总结对比
特性 | 浏览器 (Web API) | Node.js (fs module) |
---|---|---|
核心对象 | File , Blob , ArrayBuffer | Buffer , Stream |
主要读取器 | FileReader , Blob.text()/.arrayBuffer() | fs.readFile() , fs.createReadStream() |
主要写入器 | 下载 (URL.createObjectURL ), File System Access API | fs.writeFile() , fs.createWriteStream() |
权限 | 受限制,需用户触发 | 完全访问 |
操作方式 | 异步 (事件回调或 Promise) | 同步、回调、Promise 三种风格 |
主要用途 | 上传前处理、图片预览、客户端日志等 | 服务器端任何文件 I/O,如读写配置、日志、用户上传的文件存储等 |
流支持 | 一般通过 ReadableStream | 一流的 Stream 支持,性能极高 |
简单来说:
- 在浏览器中,你是客人,需要主人的许可才能看或动房间里的东西(文件)。
- 在 Node.js 中,你是主人,可以随意管理整个房子(文件系统)。