You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter桌面端Firebase Storage上传图片无法查看求助

解决Firebase云函数上传图片后无法读取的问题

问题现象

从云函数获取下载URL后,持续触发Exception: Invalid image data错误:

  • 手动下载图片到本地,提示文件格式无效或已损坏
  • Chrome中打开仅显示占位图,文件占用存储空间但无法读取
  • Firebase控制台存储桶内预览显示Error loading preview

已尝试的方案:

  • 构造公共URL、获取签名URL
  • 设置文件为公开(public: true)
  • 提升服务账号存储元数据读取权限
  • 二进制/Base64编码方式上传下载
  • 存储规则设为allow read, write: if true

问题根源

代码中存在请求字段名不匹配的问题:

  • Flutter端上传的字段是encodedFileBytes,但云函数定义的UploadFileRequest接口期望接收file字段
  • 云函数将空的data.file进行Base64解码,导致上传到存储桶的是无效数据

修复方案

1. 对齐两端字段名

修改云函数的请求字段定义,与Flutter端保持一致,确保数据正常传递。

修改后的云函数代码

import { logger } from "firebase-functions";
import { initializeApp, ServiceAccount } from "firebase-admin/app";
import { Storage } from "@google-cloud/storage";
import { onRequest } from "firebase-functions/v2/https";
import { credential } from "firebase-admin";
import { default as serviceAccountData } from "@key/service-account-key.json";

const projectID = "vra-client-service-app";

const serviceAccount = serviceAccountData as ServiceAccount;

initializeApp({
  credential: credential.cert(serviceAccount),
});

const storage = new Storage({
  projectId: projectID,
  keyFilename: "service-account-key.json",
});

// 修正字段名,与Flutter端的encodedFileBytes对齐
interface UploadFileRequest {
  encodedFileBytes: string;
  storagePath: string;
  mimeType: string;
}

interface SuccessResponse {
  message: string;
  downloadUrl: string;
}

interface ErrorResponse {
  error: string;
}

export const uploadFile = onRequest(async (request, response) => {
  console.log("Function uploadFile started");

  if (request.method !== "POST") {
    const errorResponse: ErrorResponse = { error: "Method not allowed" };
    response.status(405).json(errorResponse);
    return;
  }

  const data: UploadFileRequest = request.body;

  // 新增字段校验,提前拦截无效请求
  if (!data.encodedFileBytes) {
    const errorResponse: ErrorResponse = { error: "Missing file data" };
    response.status(400).json(errorResponse);
    return;
  }

  try {
    const bucketName = `${projectID}.appspot.com`;
    const storagePath = data.storagePath;
    const bucket = storage.bucket(bucketName);
    const file = bucket.file(storagePath);

    const decodedData = Buffer.from(data.encodedFileBytes, "base64");

    await file.save(decodedData, {
      contentType: data.mimeType,
      public: true,
    });

    const downloadUrl = await file.getSignedUrl({
      action: "read",
      expires: "03-09-2491",
    });

    const successResponse: SuccessResponse = {
      message: "File uploaded successfully",
      downloadUrl: downloadUrl[0],
    };

    response.status(200).json(successResponse);
  } catch (error: unknown) {
    if (error instanceof Error) {
      logger.error(error);
      const errorResponse: ErrorResponse = { error: error.message };
      response.status(500).json(errorResponse);
    } else {
      logger.error("Unknown error:", error);
      const errorResponse: ErrorResponse = {
        error: "An unknown error occurred",
      };
      response.status(500).json(errorResponse);
    }
  }
});

2. 验证修复效果

部署修改后的云函数后,重新上传图片:

  • 检查Firebase控制台存储桶,确认图片预览正常显示
  • 访问下载URL可正常打开图片
  • Flutter端不再抛出Invalid image data异常

内容的提问来源于stack exchange,提问作者Nana Kwame

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 21:47:42