使用 RestSharp 发送 HTTP POST Multipart/form-data 字段

Posted

技术标签:

【中文标题】使用 RestSharp 发送 HTTP POST Multipart/form-data 字段【英文标题】:Sending HTTP POST Multipart/form-data field using RestSharp 【发布时间】:2014-05-13 00:35:07 【问题描述】:

我在将 RestSharp 用于我正在处理的项目中需要使用的 REST API 时遇到问题。我需要发出的请求分为三部分:标头 API 密钥、要上传的文件和一堆 JSON 格式的数据。 API 要求使用“数据”的表单字段名称发送数据部分。由于某种原因,这会导致问题,因为它在请求正文中将字段命名为“数据”。

我的代码如下:

var request = new RestRequest(UPLOAD_DOC_URLSEGMENT, Method.POST)

    RequestFormat = DataFormat.Json,
    AlwaysMultipartFormData = true,
    JsonSerializer = new RestSharpJsonDotNetSerializer(customSerializer)
;

if (doc is DocA)
    request.AddParameter("data",doc as DocA,ParameterType.RequestBody);
    //request.AddBody(doc as DocA);
else
    request.AddParameter("data", doc as DocB,ParameterType.RequestBody);
    //request.AddBody(doc as DocB);

request.AddFile("file", doc.File.FullName);

如您所见,我尝试同时使用request.AddBody(doc) 方法和request.AddParameter(name, object, type) 方法。他们似乎都没有正确发送数据,因为我收到来自服务器的响应,说缺少所需的参数。使用提琴手我可以看到二进制数据,但看不到这两种方法的 JSON 数据。我已经浏览了 RestSharp 文档,但找不到任何可以让我将特定“字段”名称指定为表单数据主体的“数据”的内容,我认为这是导致我遇到的问题的原因.我在这里做错了什么?

编辑:在使用提琴手进一步检查后,它似乎根本没有将我的 JSON 数据添加到 HTTP 请求的正文中。但是,在上传(执行命令)之前有一个断点,我可以看到参数列表(和文件列表)中的所有内容都正确序列化。使用 Fiddler 检查时,我看到文件二进制数据,然后是多部分/表单数据边界,然后什么也没有。我会假设这是我的数据应该在的地方......

【问题讨论】:

我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。 对不起,关于那个!刚刚阅读那篇文章,感谢您的编辑。 我也在寻找它的答案。 @JNYRanger 你找到答案了吗..?如果您有解决方案,请告诉我。提前致谢。 @KevalLangalia 不。我最终放弃了 RestSharp 并使用标准的 HttpWebRequest 类和 JSON.NET 创建了自己的 REST 客户端 对于未来的访问者,此问题已在 RestSharp 上得到修复。讨论帖:github.com/restsharp/RestSharp/issues/524 【参考方案1】:

所以我通过解决使用 AddBody 方法的问题来做到这一点,该方法会自动杀死多部分表单图像并且不会发送它们。 您必须改用 add 参数。

要解决这个问题,您可能需要在通信双方做一些工作。

要从客户端发送消息,请执行以下操作:

new RestRequest("<Your URI>");
request.AddParameter("request", tokenRequest.ToJson());
request.AddFile("front", frontImage.CopyTo, "front");
request.AddFile("back", backImage.CopyTo, "back");
request.AddHeader("Content-Type", "multipart/form-data");

在我的 Web 服务端,我接受 json 作为方法的参数并手动获取对文件流的引用:

public JsonResult MyService(StoreImageRequest request)

    var frontImage = HttpContext.Request.Files["front"].InputStream;
    var backImage = HttpContext.Request.Files["front"].InputStream;

【讨论】:

这段代码对你有用吗@C Tierney。我想上传一个文件以及一些参数,但我无法让它工作。我总是收到状态码为 0 的响应。“底层连接已关闭:发送时发生意外错误。” tokenRequest 当然是未定义的并且会抛出一个异常......第一行应该是'var tokenRequest ='后面的行吗?或者,那行应该是'var request =',我遇到了这个问题/异常,这个代码sn-p对我来说没用。 token 是我想要传递的 json 对象,背面图像和正面图像也是上面的代码变量。我们对支票图像进行标记,tokenRequest 是我们想要与文件一起传递的对象,以构建与安全存储的支票图像相关联的数据集。抱歉,我没有说得更清楚。【参考方案2】:

带有 JSON 正文 + 文件部分的多部分请求

如果您的服务器可以处理包含 JSON 正文和文件部分的多部分,那么

客户端代码:

        var req = new RestRequest(UPLOAD_DOC_URLSEGMENT, Method.POST);

        req.RequestFormat = DataFormat.Json;
        req.AddBody(doc);

        req.AddFileBytes("TestImage", Properties.Resources.TestImage, "TestImage.jpg");

        req.AddHeader("apikey", "MY-API-KEY");
        var resp = restClient.Execute<ApiResult>(req);

服务器代码:

在服务器端,这样的多部分请求应该被处理为:

    [HttpPost]
    public JsonResult UploadDoc()
    
        // This is multipart request. So we should get JSON from http form part:
        MyDocModel doc = JsonConvert.DeserializeObject<MyDocModel>(Request.Form[0]);
        
        foreach (string fileName in request.Files)
        
            HttpPostedFileBase file = request.Files[fileName];
        

【讨论】:

上一个答案通过使用解决方法tokenRequest.ToJson() 解决了主题中声明的需求。这个答案建议使用有效的req.RequestFormat = DataFormat.Json

以上是关于使用 RestSharp 发送 HTTP POST Multipart/form-data 字段的主要内容,如果未能解决你的问题,请参考以下文章

使用 restsharp 在 WCF Web api 服务上发布 http 帖子

RestSharp​.net REST/HTTP 工具库

如何将此 .NET RestSharp 代码转换为 Microsoft.Net.Http HttpClient 代码?

RestSharp的简单用法

使用RESTSHARP进行OAuth 2身份验证不起作用

使用 RestSharp 在 multipart/form-data POST 中包含文件时遇到问题