C# HttpClient POST 同时上传参数与文件的实现方法

Nora
Nora
发布时间:2026-10-15 | 5人浏览过
原创

在 C# 开发中,经常遇到需要通过 HTTP POST 请求同时发送普通表单字段和文件的需求。本文将演示如何利用 HttpClient 结合 MultipartFormDataContent 类,在一个请求体中混合传递键值对参数与文件流,并包含处理 Cookie 和异常状态的完整示例。

基础实现:键值对与字节数组组合

最直观的方式是构建 MultipartFormDataContent 对象,遍历传入的参数集合,将每个字符串参数封装为 StringContent 后加入;随后读取本地文件为字节数组,使用 ByteArrayContent 添加文件部分。最后发起异步 POST 请求。

using (var client = new HttpClient())
{
    using (var multipartFormDataContent = new MultipartFormDataContent())
    {
        // 1. 准备表单参数集合
        var values = new[]
        {
            new KeyValuePair<string, string>("c", "3"),
            new KeyValuePair<string, string>("c", "2"),
            new KeyValuePair<string, string>("d", "2")
        };

        // 2. 将参数逐个添加到表单内容中
        foreach (var keyValuePair in values)
        {
            // 注意 Key 需要用双引号包裹以符合 HTTP 规范解析习惯
            multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
                String.Format("\"{0}\"", keyValuePair.Key));
        }

        // 3. 添加文件部分(此处以本地图片为例)
        multipartFormDataContent.Add(new ByteArrayContent(System.IO.File.ReadAllBytes(@"D:\test.jpg")),
            "\"pic\"",
            "\"test.jpg\"");

        // 4. 执行 POST 请求
        var requestUri = "http://localhost:8080";
        // Result 属性用于同步等待异步操作完成,生产环境建议 await
        var html = client.PostAsync(requestUri, multipartFormDataContent).Result.Content.ReadAsStringAsync().Result;
    }
}

进阶示例:含 Header 设置与 Stream 流的上传

在实际业务场景中,上传可能还需要携带自定义 Header(如 Token、Client ID)并处理 JSON 数据串。以下示例展示了如何手动配置边界符、设置 Cookie 以及使用 FileStream 进行文件上传,从而减少内存占用。

  1. 初始化客户端与请求 URL:根据需要决定是否禁用自动 Cookie 处理以便手动控制,并拼接 RPC 或 API 地址。
  2. 配置多部分表单头:生成唯一的 Boundary 字符串,显式指定 Content-Type,并注入认证信息等自定义 Header。
  3. 构建请求主体:验证文件路径有效性,打开文件流并封装为 StreamContent 添加到表单中;同时将序列化的 DTO 对象作为普通字符串字段加入。
  4. 执行与响应处理:调用 PostAsync 获取响应,检查状态码并读取返回结果,最后在 Finally 块中安全释放资源。
string reqUrl = JsonrpcHttpClient.MakeRpcUrl(typeof(Wfm_SimReport).Name, "save");
// UseCookies = false 允许手动管理 Cookie 行为
using (HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false }))
{
    string boundary = string.Format("----WebKitFormBoundary{0}", DateTime.Now.Ticks.ToString("x"));
    MultipartFormDataContent content = new MultipartFormDataContent(boundary);

    // 设置请求参数头部
    content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
    content.Headers.Add("Cookie", TokenManager.Token);
    content.Headers.Add("client", "true");

    if (string.IsNullOrEmpty(fullPath) && !File.Exists(fullPath))
    {
        return false;
    }

    string fileName = Path.GetFileName(fullPath);

    // 使用 FileStream 读取文件,更节省内存
    FileStream fStream = File.Open(fullPath, FileMode.Open, FileAccess.Read);
    content.Add(new StreamContent(fStream, (int)fStream.Length), "file", fileName);

    // 添加其他 JSON 字符串参数
    content.Add(new StringContent(JsonHelper.Serialize(entity)), "dtoStr");

    try 
    {
        var result = client.PostAsync(reqUrl, content).Result;
        if (result.IsSuccessStatusCode)
        {
            string rslt = result.Content.ReadAsStringAsync().Result;
            Debug.WriteLine(rslt);
            return true;
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(string.Format("获取服务器返回结果错误:消息:{0},堆栈:{1}",ex.Message,ex.StackTrace));
    }
    finally
    {
        // 确保文件流和客户端被正确关闭
        fStream.Close();
        client.Dispose();
    }
}

总结

通过组合 StringContent、ByteArrayContent 或 StreamContent,开发者可以灵活地在 C# 的 HttpClient 请求中嵌入文件与普通表单数据。关键在于正确设置 MultipartFormDataContent 的边界标识,并注意在异步编程模型下合理处理资源释放与异常捕获。

以上就是 C# HttpClient Post参数同时上传文件的详细内容,更多关于 C# HTTP请求开发技巧的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表