我需要使用.net core上传文件。
我正在使用多部分表单和AJAX。
但是我有一个独特的要求。我需要能够将数据添加到序列化数组,然后通过ajax POST请求和模型绑定将其绑定到控制器。
我需要添加一个ID,并将其传递给控制器。根据ID,我决定将上载的文件详细信息保存到表的哪一行。
我要发布到的控制器:
[HttpPost]
public async Task<IActionResult> File(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
var filePath = Path.GetTempFileName();
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream);
}
}
}
string fpath = filePath;
var query = from d in db.TableA
where d.File == null && d.id == id // This is where I need to compare the ID
select d;
foreach (TableA details in query)
{
details.File = filePath;
}
try
{
await db.SaveChangesAsync(); // await needed to hold execution
}
catch (Exception e)
{
Console.WriteLine(e);
}
return RedirectToAction("View");
}
其中d.File == null && d.id == id //这是我需要比较的地方
ID
多部分表格:
<form method="post" id="typea" enctype="multipart/form-data" asp-controller="Main" asp-action="File">
<label class="btn btn-info"> Upload your document <input type="file" name="files" onchange="this.form.submit()" hidden />
</label>
</form>
我的Ajax电话:
$(document).ready(function () {
$('#typea').click(function () {
event.preventDefault();
var $form = $(this);
var serializedData = $form.serializeArray();
serializedData.push({ name: "ID", value: "typea" });
$.ajax({
url: "Main/File",
type: "POST",
data: serializedData
});
});
我的问题是这样的:
如果我推送数组,我将无法依靠IFormFile接口进行模型绑定。
我可以以某种方式扩展IFormFIle接口吗?
还是有一种无需使用IFormFile就可以做到的方法。
我尝试编写从IFormFIle接口引用的我自己的模型,但是没有。
public interface IFormFile
{
string ContentType { get; }
string ContentDisposition { get; }
IHeaderDictionary Headers { get; }
long Length { get; }
string Name { get; }
string FileName { get; }
Stream OpenReadStream();
void CopyTo(Stream target);
Task CopyToAsync(Stream target, CancellationToken cancellationToken = null);
}
我不能使用接口的方法,这很明显。
请指针:)。
最佳答案
您不需要实现(扩展)IFormFile
接口,按组成进行包装优于继承。只需创建一个虚拟POCO即可保存信息:
public class IFormFilesWrapper{
public string Id {get;set;} // you might change the type to Guid / int /e.t.c
public IList<IFormFile> Files {get;set;}
}
动作方法为:
[HttpPost]
public async Task<IActionResult> File(IFormFilesWrapper filesWrapper)
{
var id = filesWrapper.Id; // here's the Id posted by client
long size = filesWrapper.Files.Sum(f => f.Length);
var filePath = Path.GetTempFileName();
foreach (var formFile in filesWrapper.Files)
{
if (formFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream);
}
}
}
// ...
}
附带说明一下,如果我没记错的话,
$form.serializeArray()
对于multipart/form-data
效果不佳。因此,我使用普通的FormData
生成有效负载:$(document).ready(function () {
$('#typea>button').click(function () {
event.preventDefault();
var form = document.querySelector("#typea");
var formData = new FormData(form);
formData.append("ID","typea");
var xhr = new XMLHttpRequest();
xhr.open("POST","Main/File");
xhr.send(formData);
});
});
屏幕截图: