采用文件上载和附加参数的WebAPI方法

Jud*_*ngo 18 asp.net asp.net-mvc file-upload asp.net-web-api

我想上传一个文件并随文件一起发送一些额外的信息,比方说一个字符串foo和一个int栏.

如何编写接收文件上载,字符串和int的ASP.NET WebAPI控制器方法?

我的JavaScript:

var fileInput = document.querySelector("#filePicker");
var formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("foo", "hello world!");
formData.append("bar", 42);

var options = {
   url: "/api/foo/upload",
   data: formData,
   processData: false // Prevents JQuery from transforming the data into a query string
};
$.ajax(options);
Run Code Online (Sandbox Code Playgroud)

我的WebAPI控制器可以像这样访问文件:

public async Task<HttpResponseMessage> Upload()
{
    var streamProvider = new MultipartMemoryStreamProvider();
    await Request.Content.ReadAsMultipartAsync(streamProvider);
    var fileStream = await streamProvider.Contents[0].ReadAsStreamAsync();
}
Run Code Online (Sandbox Code Playgroud)

但我不清楚如何获得我的字符串和我的int.我想我可以说streamProvider.Content [1],或者其他什么,但这感觉非常讨厌.

什么是正确的方法©编写接受文件上传,字符串和int的WebAPI操作?

Ben*_*ter 19

您可以创建自己MultipartFileStreamProvider的访问权限以访问其他参数.

ExecutePostProcessingAsync我们循环遍历每个文件的多部分形式并加载自定义数据(如果你只有一个文件,你将只在CustomData列表中有一个对象).

class MyCustomData
{
    public int Foo { get; set; }
    public string Bar { get; set; }
}

class CustomMultipartFileStreamProvider : MultipartMemoryStreamProvider
{
    public List<MyCustomData> CustomData { get; set; }

    public CustomMultipartFileStreamProvider()
    {
        CustomData = new List<MyCustomData>();
    }

    public override Task ExecutePostProcessingAsync()
    {
        foreach (var file in Contents)
        {
            var parameters = file.Headers.ContentDisposition.Parameters;
            var data = new MyCustomData
            {
                Foo = int.Parse(GetNameHeaderValue(parameters, "Foo")),
                Bar = GetNameHeaderValue(parameters, "Bar"),
            };

            CustomData.Add(data);
        }

        return base.ExecutePostProcessingAsync();
    }

    private static string GetNameHeaderValue(ICollection<NameValueHeaderValue> headerValues, string name)
    {
        var nameValueHeader = headerValues.FirstOrDefault(
            x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));

        return nameValueHeader != null ? nameValueHeader.Value : null;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中:

class UploadController : ApiController
{
    public async Task<HttpResponseMessage> Upload()
    {
        var streamProvider = new CustomMultipartFileStreamProvider();
        await Request.Content.ReadAsMultipartAsync(streamProvider);

        var fileStream = await streamProvider.Contents[0].ReadAsStreamAsync();
        var customData = streamProvider.CustomData;

        return Request.CreateResponse(HttpStatusCode.Created);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.我最后只使用"简单"args传递args,例如$ .post("/ api/foo?id = 23&bar = hello",fileData).这工作..提供你没有传递复杂的对象或数组.我更喜欢你的解决方案,所以我把它标记为答案. (4认同)
  • 在我们的尝试中,我们在键/值对的值部分中获取参数的名称 - 关键字段simple包含'name'.自五月以来有什么变化? (3认同)

小智 5

我认为这里的答案很好。因此,其他人可以看到一个简单的示例,该示例除了以摘要形式显示文件之外还如何传递数据,其中包括一个Javascript函数,该函数使WebAPI调用FileUpload Controller,以及来自FileUpload Controller的代码段(在VB.net中)读取从Javascript传递的其他数据。

Javascript:

            function uploadImage(files) {
            var data = new FormData();
            if (files.length > 0) {
                data.append("UploadedImage", files[0]);
                data.append("Source", "1")
                var ajaxRequest = $.ajax({
                    type: "POST",
                    url: "/api/fileupload/uploadfile",
                    contentType: false,
                    processData: false,
                    data: data
                });
Run Code Online (Sandbox Code Playgroud)

文件上传控制器:

        <HttpPost> _
    Public Function UploadFile() As KeyValuePair(Of Boolean, String)
        Try
            If HttpContext.Current.Request.Files.AllKeys.Any() Then
                Dim httpPostedFile = HttpContext.Current.Request.Files("UploadedImage")
                Dim source = HttpContext.Current.Request.Form("Source").ToString()
Run Code Online (Sandbox Code Playgroud)

因此,您可以在Javascript中看到,传递的其他数据是“ Source”键,其值为“ 1”。正如Chandrika在上面回答的那样,控制器通过“ System.Web.HttpContext.Current.Request.Form(“ Source”)。ToString()“读取此传递的数据。

请注意,Form(“ Source”)使用()(相对于[]),因为控制器代码在VB.net中。

希望这可以帮助。