如何使用Web API上传文件和提交表单数据?

时间:2015-03-19 15:00:55

标签: c# asp.net asp.net-web-api

背景

我目前正在使用C#代码从网页中读取HTTP POST表单提交中的值。它看起来像这样:

public class CompanyDTO
{
    public string CompanyName { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZIP { get; set; }
}

// POST: api/Submission
public HttpResponseMessage Post(CompanyDTO Company)
{
    return JsonToBrowser("{'location':'" + Company.City + "," + Company.State + "'}");
}

我还有工作代码从页面上的文件上传控件中读取附件:

// POST: api/Submission
public HttpResponseMessage Post()
{
    // Process and save attachments/uploaded files
    var folderName = "App_Data";
    var PATH = HttpContext.Current.Server.MapPath("~/" + folderName);
    var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
    if (Request.Content.IsMimeMultipartContent())
    {
        var streamProvider = new CustomMultipartFormDataStreamProvider(PATH);
        var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
        {
            if (t.IsFaulted || t.IsCanceled)
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }

            var fileInfo = streamProvider.FileData.Select(i =>
            {
                var info = new FileInfo(i.LocalFileName);
                return new FileDesc(info.Name, rootUrl + "/" + folderName + "/" + info.Name, info.Length / 1024);
            });
            return fileInfo;
        });

        return JsonToBrowser("{'status':'success'}");
    } 
    else 
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
    }
}

显然最后一段代码还有一些,但我希望它至少可以说明我的问题。

我的问题

我现在正在尝试将这两段代码组合在一起。我认为这就像将数据传输对象放在Post函数中一样简单:

public HttpResponseMessage Post(CompanyDTO Company)

这导致在执行HTTP POST时将以下内容返回到浏览器:

  

{“消息”:“请求实体的媒体类型'multipart / form-data'是   不支持此资源。“,”ExceptionMessage“:”不   MediaTypeFormatter可用于读取类型的对象   'CompanyDTO'来自媒体类型的内容   “多部分/格式数据”。“,   “ExceptionType”: “System.Net.Http.UnsupportedMediaTypeException”   “StackTrace”:“at   System.Net.Http.HttpContentExtensions.ReadAsAsync [T](HttpContent   content,Type type,IEnumerable1 formatters,IFormatterLogger   formatterLogger,CancellationToken cancellationToken)\ r \ n at   System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent内容,   类型类型,IEnumerable1格式化程序,IFormatterLogger formatterLogger,   取消语音取消语句)\ r \ n at   System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage   请求,类型类型,IEnumerable1格式化程序,IFormatterLogger   formatterLogger,CancellationToken cancellationToken)“}

我的问题

那么我如何使用C#和ASP.NET上传一个或多个文件并读取/处理常规表单数据字段。我正在使用Visual Studio 2013(社区版)。 另外,我是C#的初学者,所以如果你参考一个关于在哪里找到它的函数/类,我可能需要一些额外的提示/帮助。

我发现与此问题相关的最接近的SO问题是How to submit form-data with optional file data in asp.net web api,但它没有任何回复/答案......

1 个答案:

答案 0 :(得分:1)

这是我遇到此问题时的解决方案:

客户端:

 public async Task UploadImage(byte[] image, string url)
        {
            Stream stream = new System.IO.MemoryStream(image);
            HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());

            Uri resourceAddress = null;
            Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
            Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
            request.Content = streamContent;

            var httpClient = new Windows.Web.Http.HttpClient();
            var cts = new CancellationTokenSource();
            Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
        }

控制器:

public async Task<HttpResponseMessage> Post()
{
    Stream requestStream = await this.Request.Content.ReadAsStreamAsync();
    byte[] byteArray = null;
    using (MemoryStream ms = new MemoryStream())
    {
        await requestStream.CopyToAsync(ms);
        byteArray = ms.ToArray();
    }
    .
    .
    .
    return Request.CreateResponse(HttpStatusCode.OK);
}