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

使用WebClient无法从Firebase Storage下载图片

Firebase Storage带令牌URL在C# WebClient中返回400错误的解决方法

问题描述

我在Firebase Storage的image/test.png路径下存储了一张图片,尝试通过C#脚本访问。包含访问令牌的完整URL可以在Chrome浏览器中正常打开图片,但在脚本中使用该URL时返回400响应码。URL示例:https://firebasestorage.googleapis.com/v0/b/[project].com/o/[图片路径]?alt=media&token=[token]。

当前使用System.Net.WebClient实现,且处于解释器环境,无法安装额外程序集,只能使用System相关类库,原有代码如下:

using System;
using System.Net;
using System.IO;

public class Script_Instance
{
    // Define your input and output parameters
    public string RunScript(string DesignName, string UrlHighres, string UrlEdited, string Folder)
    {
        string resultMessage = "";

        // Create a WebClient instance to download images
        WebClient webClient = new WebClient();

        try
        {
            DownloadImage(DesignName, UrlHighres, Folder, "_imagelines", webClient);

            resultMessage = "Images downloaded and saved to " + Folder;
        }
        catch (WebException webEx)
        {
            resultMessage = "Error downloading image: " + webEx.Message;
        }
        catch (Exception ex)
        {
            resultMessage = "Error: " + ex.Message;
        }

        return resultMessage;
    }

    // Custom method to download and save an image
    private void DownloadImage(string name, string url, string destinationFolder, string end, WebClient webClient)
    {
        Uri uri = new Uri(url);

        // Download the image from the URL
        byte[] image_data = webClient.DownloadData(uri);

        // Extract the filename from the URL
        string file_name = name + end + ".png";

        // Create the full path to the destination file
        string destination_file = Path.Combine(destinationFolder, file_name);

        // Save the image to the destination folder
        File.WriteAllBytes(destination_file, image_data);
    }
}

问题分析与解决方案

400响应码通常表示请求格式不正确,结合浏览器能正常访问的情况,主要排查以下几个方向:

1. 缺少浏览器标识请求头

Firebase Storage可能会验证请求的User-Agent,WebClient默认的请求头没有该字段,容易被拦截。添加模拟浏览器的User-Agent即可解决。

2. URL路径未正确编码

浏览器会自动对URL中的特殊字符(如空格、特殊符号)进行编码,但WebClient构造Uri时可能不会处理路径部分的编码,导致请求格式错误。需要手动对URL的路径部分进行URL编码。

3. 增强错误排查

原有代码只捕获了错误消息,无法获取Firebase返回的具体错误内容,需要扩展WebException的处理逻辑,读取响应内容来定位问题。

修改后的完整代码

using System;
using System.Net;
using System.IO;
using System.Web;

public class Script_Instance
{
    public string RunScript(string DesignName, string UrlHighres, string UrlEdited, string Folder)
    {
        string resultMessage = "";
        WebClient webClient = new WebClient();

        try
        {
            // 添加模拟浏览器的User-Agent请求头
            webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36");
            
            // 对URL中的路径部分进行编码处理
            int oIndex = UrlHighres.IndexOf("/o/") + 3;
            int paramIndex = UrlHighres.IndexOf("?");
            if (oIndex > 0 && paramIndex > oIndex)
            {
                string pathPart = UrlHighres.Substring(oIndex, paramIndex - oIndex);
                // 替换+为%20,避免空格编码问题
                string encodedPath = HttpUtility.UrlEncode(pathPart).Replace("+", "%20");
                UrlHighres = UrlHighres.Substring(0, oIndex) + encodedPath + UrlHighres.Substring(paramIndex);
            }

            DownloadImage(DesignName, UrlHighres, Folder, "_imagelines", webClient);
            resultMessage = $"图片已下载并保存至 {Folder}";
        }
        catch (WebException webEx)
        {
            resultMessage = $"下载图片出错: {webEx.Message}";
            // 读取Firebase返回的具体错误内容
            if (webEx.Response is HttpWebResponse response)
            {
                resultMessage += $", 状态码: {(int)response.StatusCode}";
                using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                {
                    resultMessage += $", 响应内容: {reader.ReadToEnd()}";
                }
            }
        }
        catch (Exception ex)
        {
            resultMessage = $"错误: {ex.Message}";
        }
        finally
        {
            // 释放WebClient资源
            webClient.Dispose();
        }

        return resultMessage;
    }

    private void DownloadImage(string name, string url, string destinationFolder, string end, WebClient webClient)
    {
        Uri uri = new Uri(url);
        byte[] image_data = webClient.DownloadData(uri);
        string file_name = $"{name}{end}.png";
        string destination_file = Path.Combine(destinationFolder, file_name);
        File.WriteAllBytes(destination_file, image_data);
    }
}

关键修改说明

  • 添加User-Agent请求头,模拟Chrome浏览器的请求特征,绕过Firebase的请求验证。
  • 对URL中/o/之后、?之前的路径部分进行URL编码,确保特殊字符被正确转义。
  • 扩展WebException处理逻辑,获取响应状态码和具体内容,便于精准定位问题。
  • 添加finally块释放WebClient资源,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Nathan Barnes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:45:08