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

C# HttpPost文件上传认证失败,同账号Python成功如何解决?

问题描述

使用C#的HttpPost向服务器上传文件时,持续出现认证失败问题,但Python实现的相同逻辑(账号密码完全复制一致)却能成功。已尝试复制Python的请求头(UserAgent、AcceptEncoding等)、修改编码方式(ASCII/UTF8),所有尝试均无效。

原C#代码

try
{
    username = 'aaaaa'
    password = 'aa0000'
    using (var httpClient = new HttpClient())
    {
        string authInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);

        // 이미지 파일의 모든 바이트를 읽음
        byte[] imageData = File.ReadAllBytes(_sImagePath);
        var vImageContent = new ByteArrayContent(imageData);

        string sFileExtension = Path.GetExtension(_sImagePath).ToLower();
        string sMimeType;

        switch (sFileExtension)
        {
            case ".jpg":
            case ".jpeg":
                sMimeType = "image/jpeg";
                break;
            case ".png":
                sMimeType = "image/png";
                break;
            case ".bmp":
                sMimeType = "image/bmp";
                break;
            case ".gif":
                sMimeType = "image/gif";
                break;
            default:
                sMimeType = "application/octet-stream";
                break;
        }

        vImageContent.Headers.ContentType = new MediaTypeHeaderValue(sMimeType);
        using (var form = new MultipartFormDataContent())
        {
            form.Add(vImageContent, "file", Path.GetFileName(_sImagePath));

            HttpResponseMessage response = await httpClient.PostAsync(_sServerUrl, form);

            if (!response.IsSuccessStatusCode)
            {
                string responseContent = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"이미지 업로드 실패: {response.StatusCode}");
                Console.WriteLine($"응답 내용: {responseContent}");

                Console.WriteLine("요청 헤더:");
                foreach (var header in httpClient.DefaultRequestHeaders)
                {
                    Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
                }

                Console.WriteLine("요청 내용:");
                foreach (var content in form)
                {
                    Console.WriteLine(content.Headers);
                }
            }
            return response.IsSuccessStatusCode;
        }
    }
}
catch (Exception ex)
{
    // 예외 처리
    System.Windows.MessageBox.Show($"Failed to upload image: {ex.Message}");
    return false;
}

原Python代码

import requests
from requests.auth import HTTPBasicAuth

cdnServerUrl = 'http://111.111.111.111:8000/TEST'
targetFile = r'C:\Test\TEST_I_240718_140919.jpeg'
username = 'aaaaa'
password = 'aa0000'

with open(targetFile, 'rb') as img_file:
    files = {'file': img_file}
    response = requests.post(cdnServerUrl, files=files, auth=HTTPBasicAuth(username, password))

if response.status_code == 200:
    print('이미지 업로드 성공')
else:
    print('이미지 업로드 실패:', response.status_code)
    print('응답 내용:', response.text)

print(response.request.headers)

尝试添加的请求头

client.DefaultRequestHeaders.UserAgent.ParseAdd("python-requests/2.32.3");
client.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip, deflate");
client.DefaultRequestHeaders.Accept.ParseAdd("*/*");
client.DefaultRequestHeaders.Connection.ParseAdd("keep-alive");
client.DefaultRequestHeaders.Add("Cookie", "HFS_SID_=0.926163150230423");
解决方案

核心修复点

  1. 修正Basic认证编码
    Python的HTTPBasicAuth默认使用**ISO-8859-1(Latin1)**编码用户名密码组合,而原C#代码用的是UTF8。部分严格的服务器会校验编码格式,这是认证失败的核心原因。将编码改为Encoding.GetEncoding("ISO-8859-1")。

  2. 匹配请求头完整性
    确保所有请求头与Python完全一致,包括User-Agent、Accept、Accept-Encoding等,避免服务器因请求头不匹配拒绝认证。

  3. 可选:统一Multipart表单边界
    部分服务器对Multipart表单的边界格式敏感,可手动指定与Python风格一致的边界(由字母数字和'-'组成),减少格式差异。

修改后的C#代码

try
{
    string username = "aaaaa";
    string password = "aa0000";
    using (var httpClient = new HttpClient())
    {
        // 使用ISO-8859-1编码,匹配Python HTTPBasicAuth的默认行为
        string authInfo = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes($"{username}:{password}"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);

        // 完全对齐Python的请求头
        httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("python-requests/2.32.3");
        httpClient.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip, deflate");
        httpClient.DefaultRequestHeaders.Accept.ParseAdd("*/*");
        httpClient.DefaultRequestHeaders.Connection.ParseAdd("keep-alive");
        // 注意:Cookie可能是动态过期的,若服务器返回新Cookie需动态获取,不要硬编码
        // httpClient.DefaultRequestHeaders.Add("Cookie", "HFS_SID_=0.926163150230423");

        byte[] imageData = File.ReadAllBytes(_sImagePath);
        var vImageContent = new ByteArrayContent(imageData);

        string sFileExtension = Path.GetExtension(_sImagePath).ToLower();
        string sMimeType;
        switch (sFileExtension)
        {
            case ".jpg":
            case ".jpeg":
                sMimeType = "image/jpeg";
                break;
            case ".png":
                sMimeType = "image/png";
                break;
            case ".bmp":
                sMimeType = "image/bmp";
                break;
            case ".gif":
                sMimeType = "image/gif";
                break;
            default:
                sMimeType = "application/octet-stream";
                break;
        }

        vImageContent.Headers.ContentType = new MediaTypeHeaderValue(sMimeType);
        
        // 手动指定符合Python风格的表单边界
        var boundary = $"----WebKitFormBoundary{Guid.NewGuid().ToString("N")}";
        using (var form = new MultipartFormDataContent(boundary))
        {
            // 确保文件字段名和文件名与Python完全一致
            form.Add(vImageContent, "file", Path.GetFileName(_sImagePath));

            HttpResponseMessage response = await httpClient.PostAsync(_sServerUrl, form);

            if (!response.IsSuccessStatusCode)
            {
                string responseContent = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"이미지 업로드 실패: {response.StatusCode}");
                Console.WriteLine($"응답 내용: {responseContent}");

                Console.WriteLine("요청 헤더:");
                foreach (var header in httpClient.DefaultRequestHeaders)
                {
                    Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
                }

                Console.WriteLine("요청 내용:");
                foreach (var content in form)
                {
                    Console.WriteLine(content.Headers);
                }
            }
            return response.IsSuccessStatusCode;
        }
    }
}
catch (Exception ex)
{
    System.Windows.MessageBox.Show($"Failed to upload image: {ex.Message}");
    return false;
}

额外排查建议

  • 用抓包工具(如Fiddler、Charles)对比C#和Python的请求,重点检查Authorization头的Base64值、请求头的完整性、Multipart表单结构是否完全一致。
  • 若服务器返回动态Cookie,不要硬编码,先发送无文件的GET/POST请求获取有效Cookie后再执行上传。
  • 确认_sImagePath和_sServerUrl的取值与Python代码完全一致,避免路径或URL拼写错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:07:02