如何使用JavaScript将HTML表单输入内容保存为JSON文件
问题原因
fs 模块是 Node.js 服务端运行时内置的文件操作模块,普通浏览器环境下的JavaScript没有操作系统级别的文件读写权限,也不存在fs模块,你直接在前端页面脚本里导入fs必然报错,这不是配置错误,是浏览器安全沙箱的基础限制,不存在“修复前端导入fs”的方法。
你可以根据实际场景选择以下两种可行方案实现需求:
方案1:纯前端无后端,触发浏览器下载JSON文件到本地
不需要搭建服务,直接修改现有前端代码,在提交表单时把数据序列化成JSON格式的Blob对象,通过临时a标签触发浏览器下载,文件会保存到用户设置的浏览器默认下载目录。
修改后的addMovie逻辑参考:
let movies = []; const addMovie = (ev)=>{ ev.preventDefault(); let movie = { id: Date.now(), title: document.getElementById('title').value, year: document.getElementById('yr').value } movies.push(movie); document.querySelector('form').reset(); // 原有localStorage存储逻辑可以保留 localStorage.setItem('key', JSON.stringify(movies) ); // 新增:触发JSON文件下载 const jsonContent = JSON.stringify(movies, null, 2); // 第三个参数为格式化缩进,提升文件可读性 const blob = new Blob([jsonContent], { type: 'application/json' }); const downloadUrl = URL.createObjectURL(blob); const aTag = document.createElement('a'); aTag.href = downloadUrl; aTag.download = 'movies-list.json'; // 自定义下载文件名 document.body.appendChild(aTag); aTag.click(); // 清理临时DOM和URL对象,避免内存占用 document.body.removeChild(aTag); URL.revokeObjectURL(downloadUrl); } document.addEventListener('DOMContentLoaded', ()=>{ document.getElementById('btn').addEventListener('click', addMovie); // 页面加载时读取localStorage中已存的电影列表,避免刷新丢失 const savedMovies = localStorage.getItem('key'); if(savedMovies) movies = JSON.parse(savedMovies); });
注意:这个方案受浏览器安全策略限制,无法指定文件保存到用户设备的任意固定路径,也不能直接覆盖用户本地已有的同名文件,每次触发都会走浏览器默认下载流程。
方案2:需要把JSON文件持久化存储在服务端
如果你要把收集到的表单数据统一存在服务器的JSON文件里,而不是分散存在每个用户本地,需要单独编写Node.js服务端代码,在服务端脚本里引入fs模块,前端通过HTTP请求把表单数据提交给后端接口,由后端完成文件写入操作。
极简实现参考:
- 编写服务端代码(保存为
server.js,注意该文件在Node环境运行,不能放在前端页面脚本里执行)
const express = require('express'); const fs = require('fs'); const cors = require('cors'); const app = express(); app.use(cors()); app.use(express.json()); // 接收电影数据提交的接口 app.post('/save-movie', (req, res) => { const newMovie = req.body; // 读取已有JSON文件内容 fs.readFile('./movies.json', 'utf8', (err, data) => { let movieList = []; if(!err && data) movieList = JSON.parse(data); movieList.push(newMovie); // 写入更新后的内容 fs.writeFile('./movies.json', JSON.stringify(movieList, null, 2), (writeErr) => { if(writeErr) return res.status(500).json({msg: '写入失败'}); res.json({msg: '保存成功'}); }) }) }) app.listen(3000, () => console.log('服务运行在3000端口'));
- 安装依赖后启动服务:
npm init -y npm i express cors node server.js
- 修改前端提交逻辑,把数据POST给后端接口:
const addMovie = async (ev)=>{ ev.preventDefault(); let movie = { id: Date.now(), title: document.getElementById('title').value, year: document.getElementById('yr').value } // 提交数据到后端接口 await fetch('http://localhost:3000/save-movie', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(movie) }) document.querySelector('form').reset(); }
特殊场景说明
如果你开发的是Electron类桌面端应用而非普通网页,可以在Electron主进程里正常引入fs模块,通过IPC通信把渲染进程(页面侧)拿到的表单数据传给主进程,再由主进程调用fs.writeFile写入文件,这种场景下fs模块可以正常使用。
内容的提问来源于stack exchange,提问作者user19314150
相关产品推荐
相关产品推荐

