【问题标题】:MultipartMemoryStreamProvider and reading user data from MultiPart/Form DataMultipartMemoryStreamProvider 并从 MultiPart/Form Data 中读取用户数据
【发布时间】:2015-09-19 00:33:19
【问题描述】:

我有一个文件和用户数据正在从 Multipart/form 数据发布到我的 apicontroller 类中的 post 方法。 我可以毫无问题地读取文件,但无法读取用户数据。

我尝试了一些方法,例如使用模型绑定,在 post 方法中将各个字段作为方法参数传递,但我得到:没有 MediaTypeFormatter 可用于从媒体类型为“multipart/”的内容中读取类型为“FormDataCollection”的对象表单数据'。

var provider = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
foreach (var item in provider.Contents)
{
    var fieldName = item.Headers.ContentDisposition.Name.Trim('"');
    if (item.Headers.ContentDisposition.FileName == null)
    {
        var data = await item.ReadAsStringAsync();
        if (fieldname == "name")
        { 
            Name = data;
        }
        else
        {
            fileContents = await item.ReadAsByteArrayAsync();
        }
    }
}

谢谢。

【问题讨论】:

    标签: html asp.net-mvc-4 asp.net-web-api asp.net-web-api2


    【解决方案1】:

    我曾考虑根据您的评论将此添加到您的其他帖子中,但是(正如您也决定的那样),这是一个单独的问题。

    public async Task<HttpResponseMessage> Post()
    {
        if (!Request.Content.IsMimeMultipartContent())
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    
        try
        {
            string root = HttpContext.Current.Server.MapPath("~/App_Data");
    
            var provider = await Request.Content.ReadAsMultipartAsync(new MultipartFormDataStreamProvider(root));
    
            // file data
            foreach (MultipartFileData file in provider.FileData)
            {
                using (var ms = new MemoryStream())
                {
                    var diskFile = new FileStream(file.LocalFileName, FileMode.Open);
    
                    await diskFile.CopyToAsync(ms);
    
                    var byteArray = ms.ToArray();
                }
            }
    
            // form data
            foreach (var key in provider.FormData.AllKeys)
            {
                var values = provider.FormData.GetValues(key);
    
                if (values != null)
                {
                    foreach (var value in values)
                    {
                        Console.WriteLine(value);   
                    }
                }
            }
    
            return Request.CreateResponse(HttpStatusCode.Created);
        }
        catch (Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
        }
    }
    

    【讨论】:

    • 谢谢。我仍然没有在另一个问题中看到任何 cmets,并想问另一个问题,因为它的方向与我开始的方向不同。
    • 我尝试添加上述内容,但得到 - 没有 MediaTypeFormatter 可用于从媒体类型为“multipart/form-data”的内容中读取“FormDataCollection”类型的对象。
    • @user877247 - 看起来我的原始答案实际上并不能很好地与 enctype="multipart/form-data" 配合使用。我认为上面编辑的答案可能会给你你正在寻找的东西。不幸的是,我不知道如何使用 MultipartMemoryStreamProvider 获取表单数据,所以我将其更改为 MultipartFormDataStreamProvider。
    【解决方案2】:

    在我看来,OP 真的很接近。这是一些试图清楚地展示如何获取表单变量以及文件上传数据的代码。

    首先是 ApiController:

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.Http;
    
    namespace WebApplication1.Controllers
    {
        public class FormAndFileDataController : ApiController
        {
            private class FormItem
            {
                public FormItem() { }
                public string name { get; set; }
                public byte[] data { get; set; }
                public string fileName { get; set; }
                public string mediaType { get; set; }
                public string value { get { return Encoding.Default.GetString(data); } }
                public bool isAFileUpload { get { return !String.IsNullOrEmpty(fileName); } }
            }
    
            /// <summary>
            /// An ApiController to access an AJAX form post.
            /// </summary>
            /// <remarks>
            /// 
            /// </remarks>
            /// <returns></returns>
            public async Task<HttpResponseMessage> Post()
            {
    
                if (!Request.Content.IsMimeMultipartContent())
                {
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                }
    
                var provider = new MultipartMemoryStreamProvider();
    
                await Request.Content.ReadAsMultipartAsync(provider);
    
                var formItems = new List<FormItem>();
    
                // Scan the Multiple Parts 
                foreach (HttpContent contentPart in provider.Contents)
                {
                    var formItem = new FormItem();
                    var contentDisposition = contentPart.Headers.ContentDisposition;
                    formItem.name = contentDisposition.Name.Trim('"');
                    formItem.data = await contentPart.ReadAsByteArrayAsync();
                    formItem.fileName = String.IsNullOrEmpty(contentDisposition.FileName) ? "" : contentDisposition.FileName.Trim('"');
                    formItem.mediaType = contentPart.Headers.ContentType == null ? "" : String.IsNullOrEmpty(contentPart.Headers.ContentType.MediaType) ? "" : contentPart.Headers.ContentType.MediaType;
                    formItems.Add(formItem);
                }
    
                // We now have a list of all the distinct items from the *form post*.
                // We can now decide to do something with the items.
                foreach (FormItem formItemToProcess in formItems)
                {
                    if (formItemToProcess.isAFileUpload)
                    {
    
                        // This is a file. Do something with the file.  Write it to disk, store in a database.  Whatever you want to do.
    
                        // The name the client used to identify the *file* input element of the *form post* is stored in formItem.name.
                        // The *suggested* file name from the client is stored in formItemToProcess.fileName
                        // The media type (MimeType) of file (as far as the client knew) if available, is stored in formItemToProcess.mediaType
                        // The file data is stored in the byte[] formItemToProcess.data
    
                    }
                    else
                    {
                        // This is a form variable.  Do something with the form variable.  Update a DB table, whatever you want to do.
    
                        // The name the client used to identify the input element of the *form post* is stored in formItem.name.
                        // The value the client input element is stored in formItem.value.
    
                    }
                }
    
                return Request.CreateResponse(HttpStatusCode.OK);
            }
    
        }
    }
    

    以及用于测试它的 MVC 视图:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    <html>
    <head>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
        <script type="text/javascript">
    
                var hiddenForm, hiddenFile;
    
                function initialize() {
                    // Use a hidden file element so we can control the UI
                    // of the file selection interface.  The built in browser
                    // UI is not localizable to different languages.
                    hiddenFile = document.createElement("input");
                    hiddenFile.setAttribute("type", "file");
                    hiddenFile.setAttribute("style", "display: none;");
    
                    // We don't need the form really, but it makes it easy to
                    // reset the selection.
                    hiddenForm = document.createElement("form");
                    hiddenForm.appendChild(hiddenFile);
    
                    hiddenFile.onchange = function () {
                        var elementToUpdate = document.getElementById("fileNameToUpload");
                        var filesToUpload = hiddenFile.files;
                        var fileToUpload = filesToUpload[0];
                        elementToUpdate.value = fileToUpload.name;
                    }
                    document.body.appendChild(hiddenForm);
                }
                function chooseFile() {
                    hiddenFile.click();
                }
    
                function clearFile() {
                    var elementToUpdate = document.getElementById("fileNameToUpload");
                    elementToUpdate.value = "";
                    hiddenForm.reset();
                }
                function testAJAXUpload() {
    
                    // We are going to use the FormData object and jQuery
                    // to do our post test.
                    var formToPost = new FormData();
                    var formVariableNameElement = document.getElementById("variableNameToUpload");
                    var formVariableValueElement = document.getElementById("variableValueToUpload");
    
                    var formVariableName = formVariableNameElement.value || "formVar1";
                    var formVariableValue = formVariableValueElement.value || "Form Value 1";
                    var filesToUpload = hiddenFile.files;
                    var fileToUpload = filesToUpload[0];
    
                    formToPost.append(formVariableName,formVariableValue)
                    formToPost.append("fileUpload", fileToUpload);
    
                    // Call the Server.
                    $.ajax({
                        url: '@Url.HttpRouteUrl("DefaultApi", new { controller = "FormAndFileData" })',
                        type: 'POST',
                        contentType: false,
                        processData: false,
                        data: formToPost,
                        error: function (jqXHR, textStatus, errorThrown) {
                            alert("Failed: [" + textStatus + "]");
                        },
                        success: function (data, textStatus, jqXHR) {
                            alert("Success.");
                        }
                    });
    
                }
    
        </script>
    </head>
    <body>
        <input id="variableNameToUpload" type="text" placeholder="Form Variable: Name" />
        <br />
        <input id="variableValueToUpload" type="text" placeholder="Form Variable: Value" />
        <br />
        <input id="fileNameToUpload" type="text" placeholder="Select A File..." /><button onclick="chooseFile()">Select File</button><button onclick="clearFile()">Reset</button>
        <br />
        <button onclick="testAJAXUpload()">Test AJAX Upload</button>
        <script type="text/javascript">
                initialize();
        </script>
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 2015-10-12
      • 2021-12-28
      • 2016-04-02
      • 1970-01-01
      相关资源
      最近更新 更多