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

SQL Server Varbinary图片迁移至Firebase遇上传成功但无文件问题求助

问题排查与解决方案

一、当前脚本的核心问题

你的脚本显示成功但无图片上传,根源是这几个硬伤:

  1. 未读取Varbinary图片数据
    SELECT语句里没包含存储图片的Varbinary字段(假设字段名为Md_FileData),且byte[] fileData = /* Retrieve file data from reader */;是注释状态,等于上传空数据。
    修复步骤:

    • 修改查询语句,加入Varbinary字段:
      SELECT Md_ID, Md_FileName, Md_FileType, Md_Extension, Md_Title, Md_Desc, Md_FileData FROM dbo.Media
      
    • 读取该字段赋值:
      byte[] fileData = (byte[])reader["Md_FileData"];
      
  2. Firebase初始化缺失身份验证
    仅传入Bucket名称无法完成上传,Firebase需要服务账号凭据授权。
    修复:
    从Firebase控制台下载JSON格式的服务账号密钥,初始化时配置凭据:

    var firebaseStorage = new FirebaseStorage(
        firebaseStorageBucket,
        new FirebaseStorageOptions
        {
            AuthTokenAsyncFactory = async () =>
            {
                var credential = GoogleCredential.FromFile("service-account-key.json");
                var token = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
                return token;
            }
        }
    );
    
  3. 异常被吞导致“假成功”
    UploadFileToFirebase方法内的异常仅打印不冒泡,主程序无法感知单个文件上传失败,直接输出“全部成功”。
    修复:要么移除该方法内的catch块,让异常传递到主程序统一处理;要么在catch中记录错误日志,并标记任务失败状态。

二、高效迁移的优化方案

针对1500张图片的迁移场景,这些方法能提升效率与可靠性:

  • 流式读取大字段
    给ExecuteReaderAsync加上CommandBehavior.SequentialAccess优化大Varbinary字段的读取,避免内存过载:

    SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
    

    读取时用GetBytes分块读取:

    long bytesRead = 0;
    int bufferSize = 4096;
    byte[] buffer = new byte[bufferSize];
    using (MemoryStream ms = new MemoryStream())
    {
        while ((bytesRead = reader.GetBytes(reader.GetOrdinal("Md_FileData"), ms.Position, buffer, 0, bufferSize)) > 0)
        {
            ms.Write(buffer, 0, (int)bytesRead);
        }
        fileData = ms.ToArray();
    }
    
  • 控制并发上传
    用SemaphoreSlim限制并发数(比如同时上传5-10个),比串行上传大幅提升速度:

    var semaphore = new SemaphoreSlim(5);
    var tasks = new List<Task>();
    while (await reader.ReadAsync())
    {
        await semaphore.WaitAsync();
        tasks.Add(Task.Run(async () =>
        {
            try
            {
                // 读取数据、调用UploadFileToFirebase逻辑
            }
            finally
            {
                semaphore.Release();
            }
        }));
    }
    await Task.WhenAll(tasks);
    
  • 断点续传与状态追踪
    给SQL的Media表新增IsUploaded(布尔型)、FirebaseUrl(字符串型)字段。每次上传成功后更新这两个字段,失败则标记未上传。后续迁移可只处理未上传的文件,避免重复劳动。同时记录每个文件的上传日志(成功/失败原因),方便排查问题。

  • 数据一致性保障
    采用“先上传图片,再更新SQL引用”的顺序,确保只有Firebase上传成功时,才把存储路径写入SQL。必要时可使用事务,避免出现“SQL有引用但Firebase无文件”的不一致情况。


内容的提问来源于stack exchange,提问作者Zille e elahi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:18:22