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

C# WebClient参照Python requests向Trello API上传带MIME类型文件咨询

问题根源

你当前使用的 WebClient.UploadValues 仅支持普通表单编码格式的键值对提交,无法构造上传文件需要的 multipart/form-data 格式请求,因此Trello无法正确识别你传递的文件、文件名和MIME类型。另外你将base64解码后的二进制图片转成ASCII字符串的操作会直接损坏文件内容,直接保留解码后的字节数组即可。

方案1:基于WebClient的兼容实现

using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Text;

namespace RescoTrello
{
    class Program
    {
        static void Main(string[] args)
        {
            string key = "xxxx";
            string token = "yyyy";
            string trelloCardID = "zzzz";
            string url = $"https://api.trello.com/1/cards/{trelloCardID}/attachments?key={key}&token={token}";
            
            // 读取并解码base64文件内容,直接保留字节数组不要转字符串
            string base64Encoded = File.ReadAllText("C:/file.txt");
            byte[] fileBytes = Convert.FromBase64String(base64Encoded);
            string fileName = "testName.png";
            string mimeType = "image/png";

            // 构造multipart/form-data请求边界
            string boundary = "----" + DateTime.Now.Ticks.ToString("x");
            byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

            using (WebClient client = new WebClient())
            {
                client.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
                using (MemoryStream ms = new MemoryStream())
                {
                    // 写入文件字段头
                    ms.Write(boundaryBytes, 0, boundaryBytes.Length);
                    string fileHeader = $"Content-Disposition: form-data; name=\"file\"; filename=\"{fileName}\"\r\nContent-Type: {mimeType}\r\n\r\n";
                    byte[] fileHeaderBytes = Encoding.UTF8.GetBytes(fileHeader);
                    ms.Write(fileHeaderBytes, 0, fileHeaderBytes.Length);
                    // 写入文件二进制内容
                    ms.Write(fileBytes, 0, fileBytes.Length);
                    // 写入请求结束边界
                    byte[] endBoundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                    ms.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);

                    try
                    {
                        byte[] responseBytes = client.UploadData(url, "POST", ms.ToArray());
                        Rootobject resultJson = JsonConvert.DeserializeObject<Rootobject>(Encoding.UTF8.GetString(responseBytes));
                        Console.WriteLine(resultJson.id);
                    }
                    catch (WebException e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
            }
        }
    }
}

方案2:更推荐的HttpClient实现(.NET Framework 4.5+ 及所有.NET Core/.NET 版本支持)

WebClient是已经被官方标记为过时的旧API,使用HttpClient代码更简洁,也不需要手动构造请求格式:

using Newtonsoft.Json;
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace RescoTrello
{
    class Program
    {
        // HttpClient建议全局静态复用,不要每次请求新建
        private static readonly HttpClient _httpClient = new HttpClient();

        static void Main(string[] args)
        {
            string key = "xxxx";
            string token = "yyyy";
            string trelloCardID = "zzzz";
            string url = $"https://api.trello.com/1/cards/{trelloCardID}/attachments";

            string base64Encoded = File.ReadAllText("C:/file.txt");
            byte[] fileBytes = Convert.FromBase64String(base64Encoded);
            string fileName = "testName.png";
            string mimeType = "image/png";

            using (var content = new MultipartFormDataContent())
            {
                // 传递公共参数
                content.Add(new StringContent(key), "key");
                content.Add(new StringContent(token), "token");
                content.Add(new StringContent(fileName), "name");
                // 传递文件内容、文件名、MIME类型
                var fileContent = new ByteArrayContent(fileBytes);
                fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(mimeType);
                content.Add(fileContent, "file", fileName);

                try
                {
                    var response = _httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                    response.EnsureSuccessStatusCode();
                    string responseStr = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                    Rootobject resultJson = JsonConvert.DeserializeObject<Rootobject>(responseStr);
                    Console.WriteLine(resultJson.id);
                }
                catch (HttpRequestException e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:06:09