我想上传一个文件并随文件一起发送一些额外的信息,比方说一个字符串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);
我的WebAPI控制器可以像这样访问文件:
public async Task<HttpResponseMessage> Upload()
{
var streamProvider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(streamProvider);
var fileStream = await streamProvider.Contents[0].ReadAsStreamAsync();
}
但是我不清楚如何获得我的字符串和我的int。我想我可以说是streamProvider.Content [1],或者其他什么,但这感觉非常讨厌。
编写接受文件上传,字符串和int的WebAPI操作的正确方法是什么?
答案 0 :(得分:18)
您可以创建自己的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;
}
}
然后在你的控制器中:
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);
}
}
答案 1 :(得分:4)
我认为这里的答案非常好。所以其他人可以看到一个简单的例子,说明如何以摘要形式传递数据,包括一个Javascript函数,它调用FileUpload控制器,以及来自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
});
文件上传控制器:
<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()
因此,您可以在Javascript中看到,传递的其他数据是“Source”键,值为“1”。正如Chandrika上面回答的那样,Controller通过“System.Web.HttpContext.Current.Request.Form(”Source“)读取这个传递的数据.ToString()”。
注意Form(“Source”)使用()(vs. []),因为控制器代码在VB.net中。
希望这有帮助。
答案 2 :(得分:3)
您可以通过以下方式提取多个文件和多个属性:
public async Task<HttpResponseMessage> Post()
{
Dictionary<string,string> attributes = new Dictionary<string, string>();
Dictionary<string, byte[]> files = new Dictionary<string, byte[]>();
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.Contents)
{
if (file.Headers.ContentDisposition.FileName != null)
{
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = await file.ReadAsByteArrayAsync();
files.Add(filename, buffer);
} else
{
foreach(NameValueHeaderValue p in file.Headers.ContentDisposition.Parameters)
{
string name = p.Value;
if (name.StartsWith("\"") && name.EndsWith("\"")) name = name.Substring(1, name.Length - 2);
string value = await file.ReadAsStringAsync();
attributes.Add(name, value);
}
}
}
//Your code here
return new HttpResponseMessage(HttpStatusCode.OK);
}
答案 3 :(得分:1)
您可以通过以下方式执行此操作: JQuery方法:
var data = new FormData();
data.append("file", filesToUpload[0].rawFile);
var doc = {};
doc.DocumentId = 0;
$.support.cors = true;
$.ajax({
url: '/api/document/uploaddocument',
type: 'POST',
contentType: 'multipart/form-data',
data: data,
cache: false,
contentType: false,
processData: false,
success: function (response) {
docId = response.split('|')[0];
doc.DocumentId = docId;
$.post('/api/document/metadata', doc)
.done(function (response) {
});
alert('Document save successfully!');
},
error: function (e) {
alert(e);
}
});
拨打“UploadDocuement”网址api
[Route("api/document/uploaddocument"), HttpPost]
[UnhandledExceptionFilter]
[ActionName("UploadDocument")]
public Task<HttpResponseMessage> UploadDocument()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
Task<HttpResponseMessage> mytask = new Task<HttpResponseMessage>(delegate()
{
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest,
Content = "In valid file & request content type!".ToStringContent()
};
});
return mytask;
}
string root = HttpContext.Current.Server.MapPath("~/Documents");
if (System.IO.Directory.Exists(root))
{
System.IO.Directory.CreateDirectory(root);
}
var provider = new MultipartFormDataStreamProvider(root);
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
if (o.IsFaulted || o.IsCanceled)
throw new HttpResponseException(HttpStatusCode.InternalServerError);
FileInfo finfo = new FileInfo(provider.FileData.First().LocalFileName);
string guid = Guid.NewGuid().ToString();
File.Move(finfo.FullName, Path.Combine(root, guid + "_" + provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "")));
string sFileName = provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "");
FileInfo FInfos = new FileInfo(Path.Combine(root, guid + "_" + provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "")));
Document dbDoc = new Document()
{
DocumentID = 0
};
context.DocumentRepository.Insert(dbDoc);
context.Save();
return new HttpResponseMessage()
{
Content = new StringContent(string.Format("{0}|File uploaded.", dbDoc.DocumentID))
};
}
);
return task;
}
按照以下方式调用您的元数据网络API:
[Route("api/document/metadata"), HttpPost]
[ActionName("Metadata")]
public Task<HttpResponseMessage> Metadata(Document doc)
{
int DocId = Convert.ToInt32(System.Web.HttpContext.Current.Request.Form["DocumentId"].ToString());
Task<HttpResponseMessage> mytask = new Task<HttpResponseMessage>(delegate()
{
return new HttpResponseMessage()
{
Content = new StringContent("metadata updated")
};
});
return mytask;
}
答案 4 :(得分:0)
var receipents = HttpContext.Current.Request.Params [“ Receipents”]; var参与者= HttpContext.Current.Request.Params [“参与者”];
var file = HttpContext.Current.Request.Files.Count > 0 ? HttpContext.Current.Request.Files[0] : null;
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(
HttpContext.Current.Server.MapPath("~/uploads"),
fileName
);
file.SaveAs(path);
}