为什么在MVC 4中进行POST操作会抛出异常?

5

我正在尝试像这样进行POST请求:

    HttpClient hc = new HttpClient();
    byte[] bytes = ReadFile(@"my_path");

    var postData = new List<KeyValuePair<string, string>>();
    postData.Add(new KeyValuePair<string, string>("FileName", "001.jpeg"));
    postData.Add(new KeyValuePair<string, string>("ConvertToExtension", ".pdf"));
    postData.Add(new KeyValuePair<string, string>("Content", Convert.ToBase64String(bytes)));

    HttpContent content = new FormUrlEncodedContent(postData);
    hc.PostAsync("url", content).ContinueWith((postTask) => {
    postTask.Result.EnsureSuccessStatusCode();
    });

但我收到了这个异常:

无效的 URI:URI 字符串太长。

抱怨这行代码:HttpContent content = new FormUrlEncodedContent(postData);。对于小文件,它可以工作,但我不知道为什么对于更大的文件它却不能工作?

当我进行 POST 时,content 可能会更大......那么为什么它抱怨 URI 呢?

2个回答

5
你应该使用MultipartFormDataContent ( http://msdn.microsoft.com/en-us/library/system.net.http.multipartformdatacontent%28v=vs.110%29 ) 代替FormUrlEncodedContent,后者会将数据发送为“application/x-www-form-urlencoded”。因此,即使您使用POST动词,它仍然会将数据POST到包含您数据的非常长的URL,因此会出现错误。
引用:
“application/x-www-form-urlencoded”内容类型不适合发送大量二进制数据或包含非ASCII字符的文本。应该使用“multipart/form-data”内容类型来提交包含文件、非ASCII数据和二进制数据的表单。
参见:http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1

这里有一个示例供您参考:ASP.NET WebApi: 如何使用WebApi HttpClient执行带文件上传的多部分POST


谢谢!你有做这个的例子吗?这样正确吗?MultipartFormDataContent multipartFormDataContent = new MultipartFormDataContent(); multipartFormDataContent.Add(new FormUrlEncodedContent(postData)); - Cristian Boariu
@CristianBoariu 我更新了我的回答,添加了一个示例链接。 - mathieu
1
@mathieu 那个例子仍然会抛出异常,因为FormUrlEncodedContent是构建的。 - Felipe Pessoto

0

我知道这个问题已经有答案了,但我遇到了同样的问题,并发现这是FormUrlEncodedContent类的限制。错误的原因是对象的编码由Uri.EscapeDataString()处理。CodePlex上的这篇文章解释了它。最终,我想出了自己的解决方案,使用HTTPUtility类来进行URL编码。

using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web;

namespace Wfm.Net.Http
{
    public class UrlContent : ByteArrayContent
    {
        public UrlContent(IEnumerable<KeyValuePair<string, string>> content)
            : base(GetCollectionBytes(content, Encoding.UTF8))
        {
        }

        public UrlContent(byte[] content, int offset, int count) : base(content, offset, count)
        {
        }

        private static byte[] GetCollectionBytes(IEnumerable<KeyValuePair<string, string>> c, Encoding encoding)
        {
            string str = string.Join("&", c.Select(i => string.Concat(HttpUtility.UrlEncode(i.Key), '=', HttpUtility.UrlEncode(i.Value))).ToArray());
            return encoding.GetBytes(str);
        }
    }


}

我写了一篇关于如何实现它的小文章。希望这能帮助到遇到相同问题的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接