10

我一直AddParameter在我的 HTTP 请求中包含 XML 主体:

request.AddParameter(contentType, body, ParameterType.RequestBody);

但是,这似乎不适用于非字符串主体。Http.RequestBody(出于某种原因,RestSharp是一个字符串。)我尝试使用AddFile(),但我找不到任何方法来避免将“文件”编码为multipart/form,即使我只提供了一个对象。

我一点也不反对用卑鄙的反射来解决这个问题,但我希望避免仅仅为了在 HTTP 请求中发送任意数据而修改源。

编辑:关于我试图发送的请求,它们看起来像这样:

PUT ... HTTP/1.1
Accept: application/vnd...
Authorization: Basic ...
Content-Type: application/octet-stream

<arbitrary bytes>

理想情况下,我想使用相同的调用来发送不同的内容类型:

PUT ... HTTP/1.1
Accept: application/vnd...
Authorization: Basic ...
Content-Type: application/vnd...

<other arbitrary bytes>
4

6 回答 6

8

在最新版本中进行了一些修改,允许使用单个文件而无需创建多部分表单请求。这是一个显示和示例的要点:

https://gist.github.com/hallem/5faaa6bebde50641e928

于 2015-01-16T23:10:06.860 回答
5

我遇到了同样的问题。我必须只上传一个文件并使用特定的内容类型与 REST 接口进行通信。您可以将 Http.RequestBody 修改为 byte[] (以及所有依赖项),但我认为这样更容易:

我修改了 RestSharp,使其仅在文件数 > 1 或文件数 = 1 并且还有正文或其他发布数据集时才使用多部分编码。

您必须从第 288 行修改 Http.cs

if(HasFiles)

if(Files.Count > 1 || (Files.Count == 1 && (HasBody || Parameters.Any())))

对于 Http.Sync.cs 修改 PreparePostData 从

private void PreparePostData(HttpWebRequest webRequest)
{
    if (HasFiles)
    {
        webRequest.ContentType = GetMultipartFormContentType();
        using (var requestStream = webRequest.GetRequestStream())
        {
            WriteMultipartFormData(requestStream);
        }
    }

    PreparePostBody(webRequest);
}

private void PreparePostData(HttpWebRequest webRequest)
{
    // Multiple Files or 1 file and body and / or parameters
    if (Files.Count > 1 || (Files.Count == 1 && (HasBody || Parameters.Any())))
    {
        webRequest.ContentType = GetMultipartFormContentType();
        using (var requestStream = webRequest.GetRequestStream())
        {
            WriteMultipartFormData(requestStream);
        }
    }
    else if (Files.Count == 1)
    {
        using (var requestStream = webRequest.GetRequestStream())
        {
            Files.Single().Writer(requestStream);
        }
    }

    PreparePostBody(webRequest);
}

如果你使用异步版本,你必须在Http.Async.cs中修改类似上面的代码。

现在你可以像这样使用 RestSharp

IRestRequest request = new RestRequest("urlpath", Method.PUT);
request.AddHeader("Content-Type", "application/zip");
request.AddFile("Testfile", "C:\\File.zip");

Client.Execute(request);

AddFile 还提供了用于设置直接 byte[] 数据而不是路径的重载。希望有帮助。

于 2012-08-09T14:56:31.817 回答
5

在撰写本文时最新版本的 RestSharp(104 版)中,修改需要在 Http.Sync.cs 方法 PreparePostData 中,应为:

    private void PreparePostData(HttpWebRequest webRequest)
    {

        // Multiple Files or 1 file and body and / or parameters
        if (Files.Count > 1 || (Files.Count == 1 && (HasBody || Parameters.Count>0)))
        {
            webRequest.ContentType = GetMultipartFormContentType();
            using (var requestStream = webRequest.GetRequestStream())
            {
                WriteMultipartFormData(requestStream);
            }
        }
        else if (Files.Count == 1)
        {
            using (var requestStream = webRequest.GetRequestStream())
            {
                Files[0].Writer(requestStream);
            }
        }
        PreparePostBody(webRequest);
    }
于 2012-09-19T18:50:13.510 回答
4

我有同样的问题,但我不喜欢分叉代码,我不喜欢迈克尔建议的替代方案,因为文档说“RequestBody:由 AddBody() 使用(不建议直接使用)”。

相反,我用自己的替换了 RestClient.HttpFactory:

RestClient client = GetClient();

var bytes = await GetBytes();
client.HttpFactory = new FactoryWithContent { GetBytes = () => new Bytes(bytes, "application/zip") };

var request = new RestRequest();
return await client.ExecutePostTaskAsync(request);

Bytes 和 FactoryWithContent 如下所示:

public class Bytes
{
    public Bytes(byte[] value, string type)
    {
        Value = value;
        Type = type;
    }

    public byte[] Value { get; private set; }
    public string Type { get; private set; }
}

public class FactoryWithContent : IHttpFactory
{
    public IHttp Create()
    {
        var http = new Http();

        var getBytes = GetBytes;
        if (getBytes != null)
        {
            var bs = getBytes();
            http.RequestBodyBytes = bs.Value;
            http.RequestContentType = bs.Type;
        }

        return http;
    }

    public Func<Bytes> GetBytes { get; set; }
}
于 2015-01-09T14:44:55.550 回答
3

我遇到过同样的问题。结果发现 RestSharp 的行为有点奇怪。

不工作:

request.Parameters.Add(new Parameter() {
  ContentType = "application/x-www-form-urlencoded",
  Type = ParameterType.RequestBody,
  Value = bytes
});

工作(添加内容类型作为名称):

request.Parameters.Add(new Parameter() {
  Name = "application/x-www-form-urlencoded", // This is the 'funny' part
  ContentType = "application/x-www-form-urlencoded",
  Type = ParameterType.RequestBody,
  Value = bytes
});

我根据这里的评论尝试了这个解决方案:https ://github.com/restsharp/RestSharp/issues/901

其中指出“...名称值将用作 Content-Type 标头,而 contentType 值将被忽略。”

您也不必将该值添加为 Content-Type 参数,但我担心未来的错误修复可能会改变行为,然后需要使用 Content-Type 而不是名称。

于 2018-04-24T10:03:19.960 回答
0

RequestStreamCallback 方法也需要修改 Http.Async.cs。实际上,我正在努力将此修复程序放入 repo 并发布到 Nuget,因为我现在正在帮助维护该项目。这是为此创建的问题的链接:https ://github.com/restsharp/RestSharp/issues/583

于 2014-10-17T18:55:20.670 回答