如何通过HttpPostedFileBase和ViewModel一起发送上传的文件? [英] How to send uploaded file(s) via HttpPostedFileBase along with a ViewModel?
问题描述
我有一个巨大的数据对象,应该通过控制器参数映射到视图模型。我还有一个文件列表(照片),我需要在上述数据对象的数组中捕获。
I have a huge data object within which should map to a view model through controller parameter. I also have a list of files (photos) that i need to capture within an array in the aforementioned data object.
我的模特:
public class TestPerson
{
public int Id { get; set; }
public string Name { get; set; }
public string Place { get; set; }
public int Age { get; set; }
public byte[] File { get; set; }
//[FileSize(10240)]
//[FileTypes("jpg,jpeg,png")]
//public HttpPostedFileBase File { get; set; }
}
我的控制器方法:
public void SavePersonData(HttpPostedFileBase personPhoto, TestPerson person)
{
var dataObject = Request.Form["person"];
var serializer = new JavaScriptSerializer();
TestPerson personReport = serializer.DeserializeObject(dataObject, typeOf(TestPerson));
System.Console.WriteLine("dummy line");
}
我的.cshtml页面:
My .cshtml page:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
<div id="testKo">
Name: <input type="text" data-bind="value: Name"/>
Place: <input type="text" data-bind="value: Place" /><br />
Age: <input type="text" data-bind="value: Age" /><br />
<input type="button" id="submitForm" class="btn-lg" value="Submit" />
</div>
<form id="photoForm" method="post" enctype="multipart/form-data">
<input type="hidden" id="personId" name="person" />
<input type="file" id="personPhotoId" name="personPhoto" />
</form>
<script>
$(document).ready(function () {
$(document).ready(function () {
var element = document.getElementById("testKo");
ko.applyBindings(viewModel, element);
$("#submitForm").on("click", function () {
var vmData = ko.toJSON(viewModel);
//$("#personId").val({ person: vmData });
var formData = new FormData($("#photoForm")[0]);
formData.append("person", vmData, "person");
//var data = new FormData();
//data.append("vmData", vmData);
//data.append("photo", $("#personPhoto").get(0).files[0])
$.ajax({
type: "POST",
url: '@Url.Action("SavePersonData", "Home")',
//cache: false,
//async: false,
contentType: false,
processData: false,
enctype: "multipart/form-data",
dataType: "json",
//data: {
// testPerson: vmData
//},
//data: {
// personPhoto: formData,
// person: vmData
//},
data: formData,
success: function (data) {
alert("success!");
}
});
});
});
function generatedViewModel() {
var self = this;
self.Id = ko.observable("1");
self.Name = ko.observable();
self.Place = ko.observable();
self.Age = ko.observable();
self.File = ko.observable();
}
var viewModel = new generatedViewModel();
});
</script>
我有什么方法可以使用此代码在我的控制器操作方法中接收这两个参数?或者我需要以任何方式调整它吗?我只需要将包括文件/图像上传数据和非表格数据对象在内的所有内容发送到我的控制器方法。
Is there any way i can receive both the parameters in my controller action method with this code? Or do i need to tweak it in any way? I just need to send all the content including file / image upload data and non-form data object to my controller method.
任何帮助都将非常感谢!
Any help would be greatly appreciated!.
推荐答案
嗯,对此最好的解决方案是在另一个内部进行2个同步的ajax调用。首先发送personPhoto数据然后将其转换为字节数组并将其设置为Session变量,并在此ajax调用的成功事件中,对main方法进行另一个ajax调用,在该方法中处理Form / Model数据并使用personPhoto的缓存会话对象。
Well, the best solution for this would be to make 2 synchronized ajax calls one within the other. Send the "personPhoto" data first and then convert it into byte array and set it as a Session variable and in the success event of this ajax call, make another ajax call to the main method where you process the Form / Model data and use the cached session object for the "personPhoto".
用以下代码替换你的ajax代码:
Replace your ajax code with the following:
var data = new FormData($("#photoForm").get(0));
$.ajax({
type: "POST",
url: '@Url.Action("CacheUploads", "Home")',
data: data,
processData: false,
contentType: false,
dataType: "json",
success: function () {
var vmData = ko.toJS(viewModel);
$.ajax({
type: "POST",
url: '@Url.Action("SavePersonData", "Home")',
data: { person: vmData },
success: function (data) {
}
});
}
});
并用以下内容替换您的控制器方法:
And replace your controller methods with the following:
public void SavePersonData(TestPerson person)
{
// You no longer need to deserialize as you'll have data properly mapped to the TestPerson object.
//var dataObject = Request.Form["person"];
//var serializer = new JavaScriptSerializer();
//object personReport = serializer.DeserializeObject(dataObject);
person.File = (byte[])Session["UploadedPhoto"];
System.Console.WriteLine("dummy line");
}
public JsonResult CacheUploads(HttpPostedFileBase personPhoto)
{
byte[] photoAsBytes = null;
using (var binaryReader = new BinaryReader(personPhoto.InputStream))
{
photoAsBytes = binaryReader.ReadBytes(personPhoto.ContentLength);
}
Session.Add("UploadedPhoto", photoAsBytes);
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
没有其他方法可以将FormData和非Form ViewModel数据一起处理在单个ajax调用中。这是我从解决方案的角度来看最接近的。祝你好运!
There is no other way you can handle FormData and Non-Form ViewModel data together in a single ajax call. This is the closest I can get from a solution perspective. Good Luck!.
这篇关于如何通过HttpPostedFileBase和ViewModel一起发送上传的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!