我有一个文件和用户数据,从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();
}
感谢。
答案 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);
}
}