JavaScript如何操作文件对象【教程】

JavaScript无法直接读写本地文件系统,所有File对象必须由用户交互触发获取,通过FileReader读取内容,用FormData上传,且仅能操作内存中的文件引用而非磁盘文件。

JavaScript 本身无法直接读写本地文件系统(出于安全限制),所谓“操作文件对象”实际是指在浏览器环境中处理用户通过 选择的 FileBlob 对象——不是操作磁盘文件,而是操作内存中的文件引用。

File 对象从哪来?必须由

用户主动触发

浏览器禁止脚本自动访问用户文件。所有合法的 File 对象都源于用户交互:

  • 点击 后在 change 事件中取 event.target.files[0]
  • 拖拽文件到页面,从 drop 事件的 event.dataTransfer.files[0] 获取
  • new File([blob], "name.txt", {type: "text/plain"}) 构造测试用对象(仅内存,不写磁盘)

试图绕过这些方式(比如用路径字符串 new File([""], "/etc/passwd"))会创建一个空、无内容、type 为空的无效对象。

读取文件内容:用 FileReader 而非 fs 模块

Node.js 的 fs.readFile 在浏览器里不存在。必须用异步的 FileReader

const reader = new FileReader();
reader.onload = () => {
  console.log(reader.result); // 文本内容或 base64 字符串
};
reader.onerror = () => {
  console.error("读取失败:", reader.error);
};
reader.readAsText(file); // 或 readAsDataURL(), readAsArrayBuffer()

注意点:

  • readAsText() 默认用 UTF-8 解码,可传第二个参数指定编码(如 "GBK",但兼容性差)
  • readAsDataURL() 适合预览图片,但大文件会生成超长字符串,内存压力大
  • 不能 await FileReader,需封装 Promise(常见漏掉的异步处理)

获取文件元信息:name/size/type 是只读属性

File 继承自 Blob,因此有以下稳定可用字段:

  • file.name:用户选择时的原始文件名(可能含路径,但浏览器已剥离,只留 basename)
  • file.size:字节数,数字类型,可直接用于大小判断(如 if (file.size > 10 * 1024 * 1024)
  • file.type:MIME 类型(如 "image/png"),但不可靠——依赖浏览器 sniff 或用户系统注册表,可能为空或错误
  • file.lastModified:毫秒时间戳,可用 new Date(file.lastModified) 转为日期对象

别尝试修改 file.name 来“重命名”,它只读;真要改名,得用 new File([file], "new-name.jpg", {type: file.type}) 构造新对象。

上传文件:用 FormData 配合 fetch

浏览器中“保存文件”只能靠用户手动下载(a.download + URL.createObjectURL()),而“上传”是唯一能真正把文件发到服务器的操作:

const formData = new FormData();
formData.append("upload", file); // 键名按后端要求填
fetch("/api/upload", {
  method: "POST",
  body: formData // 不要设 Content-Type,让浏览器自动设 multipart/form-data
});

关键细节:

  • 不要手动设置 headers: {"Content-Type": "multipart/form-data"},这会破坏 boundary,导致后端收不到文件
  • 若需额外字段(如 token),用 formData.append("token", "abc") 即可,同传
  • 大文件建议加进度监听:xhr.upload.onprogress(fetch 目前无原生进度 API,需用 ReadableStream 分块读取再上传)

真正的难点不在语法,而在对“浏览器沙箱模型”的理解——所有操作都围绕用户授权展开,任何脱离 File 实例的路径操作、同步读取、磁盘写入,都会失败或被拦截。