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

使用C# HttpClient上传文件及键值对至eQSL.cc时返回空响应问题

使用C# HttpClient上传ADIF文件到eQSL.cc时响应为空的解决方法

我正尝试用C#的HttpClient向eQSL.cc上传ADIF日志文件,用curl命令能正常得到响应,但C#代码返回状态码OK,响应内容却是空字符串。

curl命令:

curl -X POST https://www.eQSL.cc/qslcard/ImportADIF.cfm -F "Filename=@D:\Documents\SourceCode\Radio\bin\Debug\net8.0-windows\logfile.adi"

curl收到的响应示例:

<!-- Reply form eQSL.cc ADIF Real-time Interface -->
etc.....

我的C#代码:

using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            HttpClient client = new HttpClient();
            string response = UploadLog(client).Result;
        }

        private static async Task<string>  UploadLog(HttpClient client)
        {
            string url = @"https://www.eQSL.cc/qslcard/ImportADIF.cfm";
            string filePath = @"D:\Documents\SourceCode\Radio\bin\Debug\net8.0-windows\logfile.adi";

            byte[] bytes = System.IO.File.ReadAllBytes(filePath);

            MultipartFormDataContent formContent = new MultipartFormDataContent();
            FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            StreamContent fileContent = new StreamContent(fileStream);

            fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
            {
                Name = "Filename",
                FileName = System.IO.Path.GetFileName(filePath)
            };

            formContent.Add(fileContent);
            formContent.Add(new StringContent("myUserID"), "EQSL_USER");
            formContent.Add(new StringContent("myPass"), "EQSL_PSWD");

            var response = await client.PostAsync(url, formContent);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }
    }
}

问题分析与修复方案

curl能正常工作但C#代码返回空响应,核心原因是请求格式未与curl完全匹配,或资源未正确处理。以下是关键修复点:

1. 正确管理文件流资源

FileStream和StreamContent未用using包裹,可能导致数据未完全发送就被截断。添加using语句确保资源自动释放,避免数据丢失。

2. 匹配curl的Content-Disposition格式

curl发送的表单字段名和文件名会包含双引号,部分服务器严格要求这种格式,需要手动为Name和FileName添加双引号。

3. 设置正确的Content-Type

ADIF是纯文本格式,curl会自动推断Content-Type,而HttpClient默认不设置,需要手动指定为text/plain。

4. 避免同步阻塞导致的问题

Main方法中使用.Result可能引发死锁,改用async/await实现异步调用。


修改后的完整代码

using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            using HttpClient client = new HttpClient();
            // 若curl依赖已登录会话,先调用登录方法获取cookie
            // await Login(client);
            string response = await UploadLog(client);
            Console.WriteLine(response);
        }

        // 可选:登录逻辑,用于获取eQSL会话cookie
        private static async Task Login(HttpClient client)
        {
            var loginData = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("username", "myUserID"),
                new KeyValuePair<string, string>("password", "myPass")
            });
            var loginResponse = await client.PostAsync("https://www.eQSL.cc/login.cfm", loginData);
            loginResponse.EnsureSuccessStatusCode();
        }

        private static async Task<string> UploadLog(HttpClient client)
        {
            string url = @"https://www.eQSL.cc/qslcard/ImportADIF.cfm";
            string filePath = @"D:\Documents\SourceCode\Radio\bin\Debug\net8.0-windows\logfile.adi";

            using MultipartFormDataContent formContent = new MultipartFormDataContent();
            
            using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            using StreamContent fileContent = new StreamContent(fileStream);
            
            // 匹配curl的Content-Disposition格式,添加双引号
            fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
            {
                Name = "\"Filename\"",
                FileName = $"\"{Path.GetFileName(filePath)}\""
            };
            
            // 设置ADIF文件的Content-Type
            fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

            formContent.Add(fileContent);
            formContent.Add(new StringContent("myUserID"), "EQSL_USER");
            formContent.Add(new StringContent("myPass"), "EQSL_PSWD");

            var response = await client.PostAsync(url, formContent);
            response.EnsureSuccessStatusCode();
            
            return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }
    }
}

额外注意事项

  • 如果你的curl命令是在已登录的终端环境下执行的(比如浏览器已登录eQSL),curl会自动使用本地cookie,而C#的HttpClient是全新会话,需先调用登录接口获取会话cookie再执行上传。
  • 可使用Fiddler等工具对比curl和C#代码发送的请求头、表单数据,快速定位格式差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 18:43:10