如何将Editor.js生成的复杂JSON数据上传至Firebase Firestore?
问题
我正在使用React JS与Editor.js开发博客应用,Editor.js返回的数据为JSON对象。目前我已接入Firebase,想要将这些数据上传至Firestore,但该JSON结构较为复杂。
Editor.js返回的JSON示例:
{ "time": 1683888680625, "blocks": [ { "id": "mhTl6ghSkV", "type": "paragraph", "data": { "text": "Hey. Meet the new Editor. On this picture you can see it in action. Then, try a demo 🤓" } }, { "id": "l98dyx3yjb", "type": "header", "data": { "text": "Key features", "level": 3 } }, { "id": "os_YI4eub4", "type": "list", "data": { "type": "unordered", "items": [ "It is a block-style editor", "It returns clean data output in JSON", "Designed to be extendable and pluggable with a simple API" ] } }, { "id": "TcUNySG15P", "type": "paragraph", "data": { "text": "Workspace in classic editors is made of a single contenteditable element, used to create different HTML markups. Editor.js workspace consists of separate Blocks: paragraphs, headings, images, lists, quotes, etc. Each of them is an independent <sup data-tune=\"footnotes\">1</sup> contenteditable element (or more complex structure) provided by Plugin and united by Editor's Core." }, "tunes": { "footnotes": [ "It works more stable then in other WYSIWYG editors. Same time it has smooth and well-known arrow navigation behavior like classic editors." ] } }, { "id": "XKNT99-qqS", "type": "attaches", "data": { "file": { "url": "https://drive.google.com/user/catalog/my-file.pdf", "size": 12902, "name": "file.pdf", "extension": "pdf" }, "title": "My file" } }, { "id": "hZAjSnqYMX", "type": "image", "data": { "file": { "url": "assets/codex2x.png" }, "withBorder": false, "withBackground": false, "stretched": true, "caption": "CodeX Code Camp 2019" } } ] }
核心需求:先将JSON中包含的图片/文件上传至Firebase Storage,更新对应URL后,再将完整JSON上传至Firestore,请问如何实现这一流程?
解决方案
步骤1:识别需上传的资源块
遍历Editor.js返回的blocks数组,筛选出type为image或attaches的块——这两类块包含需要上传到Storage的文件资源。注意区分本地文件(用户刚选择的File对象)和已存在的线上URL(无需重复上传)。
步骤2:封装Firebase Storage上传函数
先写一个通用的文件上传函数,负责将本地文件上传到Storage并返回下载URL:
import { storage, firestore } from './firebaseConfig'; // 导入你的Firebase配置文件 import { ref, uploadBytes, getDownloadURL } from "firebase/storage"; import { doc, setDoc } from "firebase/firestore"; // 上传文件到Storage并返回下载URL const uploadFileToStorage = async (file, storagePath) => { const storageRef = ref(storage, storagePath); await uploadBytes(storageRef, file); return getDownloadURL(storageRef); };
步骤3:批量处理资源并更新JSON
遍历所有块,对包含本地文件的块执行上传操作,替换原URL为Storage返回的新URL,最后将更新后的JSON上传到Firestore:
const saveEditorData = async (editorData) => { // 深拷贝原数据,避免修改编辑器原始状态 const updatedData = JSON.parse(JSON.stringify(editorData)); // 遍历处理每个块 for (const block of updatedData.blocks) { // 处理图片块 if (block.type === 'image') { const file = block.data.file; // 判断是否为本地File对象(而非线上URL) if (file instanceof File) { // 生成唯一存储路径,避免文件名冲突 const storagePath = `blog-images/${Date.now()}-${file.name}`; const newUrl = await uploadFileToStorage(file, storagePath); // 更新块中的文件URL block.data.file = { url: newUrl }; } } // 处理附件块 else if (block.type === 'attaches') { const file = block.data.file; if (file instanceof File) { const storagePath = `blog-attachments/${Date.now()}-${file.name}`; const newUrl = await uploadFileToStorage(file, storagePath); // 完整更新附件信息(URL、大小、文件名、扩展名) block.data.file = { url: newUrl, size: file.size, name: file.name, extension: file.name.split('.').pop() }; } } } // 将更新后的JSON上传到Firestore try { // 生成唯一文档ID,也可自定义业务ID const blogDocRef = doc(firestore, 'blogs', `blog-${Date.now()}`); await setDoc(blogDocRef, updatedData); console.log('博客数据保存成功'); } catch (err) { console.error('保存失败:', err); } };
步骤4:绑定Editor.js保存事件
在编辑器的保存按钮点击事件中,调用上述函数:
// 假设editor是Editor.js的实例 const handleEditorSave = async () => { const editorData = await editor.save(); await saveEditorData(editorData); };
关键注意事项
- 异步顺序控制:使用
async/await确保所有文件上传完成后再更新JSON并提交到Firestore,避免数据不一致。 - Storage权限:开发环境可临时设置Storage规则为公开读写,生产环境必须配置严格的安全规则(仅允许认证用户上传/访问)。
- 错误处理:在上传和保存过程中添加try/catch,捕获网络异常、权限不足等错误并提示用户。
- 重复上传判断:通过判断
file是否为File对象,避免重复上传已存在的线上URL资源。
内容的提问来源于stack exchange,提问作者Mohammed Bekele
相关产品推荐
相关产品推荐

