MultipartMemoryStreamProvider并从MultiPart / Form Data中读取用户数据

时间:2015-07-01 17:49:26

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

我有一个文件和用户数据,从Multipart /表格数据发布到我的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();
}

感谢。

2 个答案:

答案 0 :(得分:4)

在我看来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 View来测试它:

@{
    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>

答案 1 :(得分:2)

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

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);
    }
}