返回

Vue + Firebase:解决 TinyMCE 图片上传 then 报错问题

vue.js

Vue.js + Firebase:TinyMCE 图片上传 'then' 读取 undefined 属性问题解析

当使用 Vue.js 集成 TinyMCE 和 Firebase 实现图片上传功能时,可能会遇到 “Cannot read properties of undefined (reading 'then')” 错误。 这个问题通常表明 uploadBytes 操作返回了一个 Promise,但它没有正确处理,导致 then 方法调用失败。 这篇文章会详细分析问题原因,并提供切实可行的解决方案。

问题分析

错误通常发生在 images_upload_handler 配置项的回调函数中。 在这里,uploadBytes 返回的 Promise 链中的某个环节出现问题。 主要原因通常是以下几个方面:

  • 异步操作未返回 Promise: uploadBytes 必须正确返回一个 Promise,否则链式调用的 then 就无法工作。
  • successfailure 回调调用不正确: TinyMCE 依赖 successfailure 这两个回调函数来通知图片上传结果。 如果未能正确调用,图片可能无法在编辑器中显示。
  • ** getDownloadURL 调用参数错误** :通常 getDownloadURL 需要传入 storage 上下文,需要确认使用正确 ref 传入。
  • 变量作用域混淆:images_upload_handler 中如果对变量作用域没有管理好可能会产生错误。

解决方案一: 确保 uploadBytes 和 getDownloadURL 返回正确的 Promise

最常见的错误是 uploadBytesgetDownloadURL 没能正确返回一个 Promise 对象, 或者未采用 Promise 链。 我们应该显式地确保每个异步操作都正确地被包装在一个Promise中,并使用链式 then 进行处理。

操作步骤:

  1. 确认 Firebase 存储 SDK 是否已正确初始化,并且 storage 实例已经可用。
  2. 使用正确的 storage 引用 blogImagestorageRef 参数传给 uploadBytesgetDownloadURL
  3. 确保 uploadBytesgetDownloadURL 方法链的 then 回调都能够被正确的执行。

代码示例:

import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage";
import { storage } from "./firebase";  // 确保这里的路径正确

const storageRef = ref;


  images_upload_handler: function (blobInfo, success, failure) {
      const blob = blobInfo.blob();
      const blogImagestoragePath = `images/blogImages/${blobInfo.filename()}`;
      const blogImagestorageRef  = storageRef(storage, blogImagestoragePath); 


      uploadBytes(blogImagestorageRef, blob)
        .then((snapshot) => {
           return getDownloadURL(blogImagestorageRef); 
        })
        .then((downloadURL) => {
          if (downloadURL) {
             success(downloadURL);
          } else {
            failure('Cannot put the image in TinyMCE');
          }
        })
         .catch((error) => {
            failure(error)
            console.error("上传或获取URL时出错", error);
        })
  }

详细解释:

  • 引入 Firebase 存储相关方法,并确保 storage 实例已初始化。
  • 使用 uploadBytes(blogImagestorageRef, blob) 执行上传,它会返回一个Promise。
  • 在第一个 then 回调中, 获取下载 URL, getDownloadURL(blogImagestorageRef)也必须返回一个 Promise。
  • 在第二个 then 中,判断是否成功取得 URL,如果成功,调用 success(downloadURL) , 将图片URL传递给 TinyMCE 。如果出错调用 failure ,反馈错误信息,最后,在 Promise链最后加入 .catch 处理链中发生的错误,同时在控制台输出方便问题排查。

解决方案二:排查 Firebase 配置问题

如果确保代码逻辑无误, 还要考虑Firebase配置是否存在问题。例如,可能缺少存储权限或者Firebase没有被正确的初始化。

操作步骤:

  1. 检查 Firebase 项目的规则是否允许读取和写入。可以在 Firebase 控制台的 Storage 部分查看。
  2. 确认 firebase 初始化部分的代码是否被正确执行。 检查 firebase.js 文件中 Firebase 初始化是否正确完成,特别是存储实例 const storage = getStorage(app); 的配置 。

Firebase 存储规则示例:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /images/blogImages/{allPaths=**} {
      allow read: if true;
      allow write: if request.auth != null;
    }
  }
}

详细解释:
此规则允许任何人读取 images/blogImages/ 下的文件,但只允许授权用户写入,你需要根据自己的应用场景调整规则。

安全建议:

  • 服务器端验证: 不要直接信任客户端上传的数据。 最好在服务器端进行文件验证和大小限制。 这样可以减少潜在的安全风险。
  • 细粒度访问控制: 根据用户角色设置详细的访问控制规则。 例如,管理员可以上传图片,但普通用户则不行。
  • 文件扩展名校验: 上传文件之前,必须校验其扩展名,以防止用户上传可执行脚本。
  • 路径前缀保护: 添加用户 ID 或会话信息在 Firebase 存储路径前,以防止跨用户访问或重写。 例如: images/users/{uid}/{blobInfo.filename()}

使用以上方法,能够有效地解决“Cannot read properties of undefined (reading 'then')”这个问题。同时,增强代码的健壮性与安全性。