通过 ajax 上传文件不会在 MVC 的请求中附加文件
File upload through ajax does not append file in Request in MVC
我有一个简单的表单,其中包含一个只接受图像的文件类型的输入。
我只想 post 将文件保存在 table 以及服务器中。
下面是我的cshtml
@using (Html.BeginForm("UploadSlider", "Admin", FormMethod.Post, new { id = "frmUploadSliderImage", @class = "form-admin" }))
{
<h2 class="form-login-heading">upload images</h2>
<div class="login-wrap">
<span class="btn btn-default btn-file">
Browse <input type="file" id="sliderFile" multiple="multiple">
</span>
<span class="text-muted" id="filePlaceHolder">No files selected</span>
<span class="text-danger"></span>
<button class="btn btn-theme btn-block" name="upload" onclick="javascript: ValidateSliderImageandPost('frmUploadSliderImage', this);" id="btnUploadSliderImage" type="submit"><i class="fa fa-upload"></i> UPLOAD</button>
</div>
}
这是我的 js ajax 部分
function ValidateSliderImageandPost(form, ctrl) {
$("#" + form).on("submit", function (e) {
e.preventDefault();
var formContainer = $('#' + form + ' .text-danger');
var formdata = new FormData();
var fileInput = $('#sliderFile');
if ($(fileInput).get(0).files.length == 0)
{
$('.btn-file :file').parent().siblings().filter(".text-danger").html('Please select a file!');
}
if ($(formContainer).text().length == 0) {
run_waitMe('Uploading! Please wait...', 'stretch', '.container');
$.each($(fileInput).get(0).files, function (index,value) {
formdata.append($(this).attr('name'), $(this));
});
postData('UploadSlider', formdata, '.upslider .status');
if (msg) {
$(".container").find('#cont').waitMe('hide');
$("#" + form).find('input[type=text], textarea').val('').removeClass("alert-success");
}
else {
$(".container").find('#cont').waitMe('hide');
$("#" + form).find('input[type=text], textarea').removeClass("alert-success");
}
}
$("#" + form).unbind('submit');
return false;
});
}
function postData(url,data,target)
{
$.ajax({
url: url,
type: "POST",
dataType: 'json',
data: data,
processData: false,
contentType:false,
success: function (data) {
if (data.result) {
animateStatus("success", data.message, target);
msg = true;
}
else {
animateStatus("fail", data.message, target);
msg = false;
}
},
error:
function (data) {
animateStatus("fail", data.message, target);
msg = false;
}
});
}
这是我的控制器部分
[HttpPost]
public JsonResult UploadSlider()
{
bool valid = false;
bool val = false;
if (Request.Files.Count > 0)
{
valid = true;
}
else
{
return Json(new { result = false, message = "Something went wrong! Please try again!" });
}
if (valid)
{
List<string> fil = new List<string>();
foreach (HttpPostedFileBase f in Request.Files)
{
HttpPostedFileBase file = f; //Uploaded file
string fileName = file.FileName;
fil.Add("./Images/Galllery/" + fileName);
System.IO.Stream fileContent = file.InputStream;
file.SaveAs(Server.MapPath("~/Images/Gallery/") + fileName);
}
using (var context = new MCBConnectionString())
{
foreach (string path in fil)
{
tbl_slider slider = new tbl_slider();
slider.slurl = path;
slider.slalt = "";
context.tbl_slider.Add(slider);
context.SaveChanges();
val = true;
}
}
if (val)
{
return Json(new { result = true, message = "Uploaded video successfully." });
}
else
{
return Json(new { result = false, message = "Could not upload video. Please try again!" });
}
}
return Json(new { result = false, message = "Could not upload video. Please try again!" });
}
当我调试和检查 Request.Files.Count 时,它将始终为零。是否有任何替代解决方法,或者我在 post 处理文件时是否犯了任何错误。我已经关注了thislink并根据自己的需要进行了修改
而不是:
$.each($(fileInput).get(0).files, function (index, value) {
formdata.append($(this).attr('name'), $(this));
});
您可能会使用:
$.each($(fileInput).get(0).files, function (index, value) {
formdata.append(value.name, value);
});
主要区别在于,使用您的方法,Content-Disposition 部分不包含 filename
,因此 ASP.NET 无法将其识别为文件内容:
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO
Content-Disposition: form-data; name="foo.png"
[object Object]
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO
Content-Disposition: form-data; name="bar.png"
[object Object]
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO--
按照我的方法,请求将如下所示:
------WebKitFormBoundary1ERBVX0wzdVczcR0
Content-Disposition: form-data; name="foo.png"; filename="foo.png"
Content-Type: imag/png
[object Object]
------WebKitFormBoundary1ERBVX0wzdVczcR0
Content-Disposition: form-data; name="bar.png"; filename="bar.png"
Content-Type: image/png
[object Object]
------WebKitFormBoundary1ERBVX0wzdVczcR0--
现在你可以看到实际的区别了。在第一种情况下,您没有 filename
也没有 Content-Type
文件,ASP.NET 只是将这些元素视为标准形式的发布数据而不是文件。
此外,您可以考虑将其替换为一些通用名称,而不是使用实际文件名 name
:
$.each($(fileInput).get(0).files, function (index, value) {
formdata.append('sliderFiles', value);
});
现在您可以通过使用 List<HttpPostedFileBase>
参数而不是使用 Request.Files
:
来进一步改进您的控制器操作
[HttpPost]
public ActionResult UploadSlider(List<HttpPostedFileBase> sliderFiles)
{
...
}
关于您的代码的另一个评论是 HTML5 FormData
在顺序浏览器中不可用,您的代码将默默地失败。如果您需要支持旧版浏览器,您可能需要通过测试浏览器的功能来执行渐进式增强,如果浏览器不支持 FormData:
,则回退到标准格式 POST
$("#" + form).on("submit", function (e) {
if(window.FormData === undefined) {
// The browser doesn't support uploading files with AJAX
// falling back to standard form upload
} else {
// The browser supports uploading files with AJAX =>
// we prevent the default form POST and use AJAX instead
e.preventDefault();
...
}
});
我有一个简单的表单,其中包含一个只接受图像的文件类型的输入。 我只想 post 将文件保存在 table 以及服务器中。
下面是我的cshtml
@using (Html.BeginForm("UploadSlider", "Admin", FormMethod.Post, new { id = "frmUploadSliderImage", @class = "form-admin" }))
{
<h2 class="form-login-heading">upload images</h2>
<div class="login-wrap">
<span class="btn btn-default btn-file">
Browse <input type="file" id="sliderFile" multiple="multiple">
</span>
<span class="text-muted" id="filePlaceHolder">No files selected</span>
<span class="text-danger"></span>
<button class="btn btn-theme btn-block" name="upload" onclick="javascript: ValidateSliderImageandPost('frmUploadSliderImage', this);" id="btnUploadSliderImage" type="submit"><i class="fa fa-upload"></i> UPLOAD</button>
</div>
}
这是我的 js ajax 部分
function ValidateSliderImageandPost(form, ctrl) {
$("#" + form).on("submit", function (e) {
e.preventDefault();
var formContainer = $('#' + form + ' .text-danger');
var formdata = new FormData();
var fileInput = $('#sliderFile');
if ($(fileInput).get(0).files.length == 0)
{
$('.btn-file :file').parent().siblings().filter(".text-danger").html('Please select a file!');
}
if ($(formContainer).text().length == 0) {
run_waitMe('Uploading! Please wait...', 'stretch', '.container');
$.each($(fileInput).get(0).files, function (index,value) {
formdata.append($(this).attr('name'), $(this));
});
postData('UploadSlider', formdata, '.upslider .status');
if (msg) {
$(".container").find('#cont').waitMe('hide');
$("#" + form).find('input[type=text], textarea').val('').removeClass("alert-success");
}
else {
$(".container").find('#cont').waitMe('hide');
$("#" + form).find('input[type=text], textarea').removeClass("alert-success");
}
}
$("#" + form).unbind('submit');
return false;
});
}
function postData(url,data,target)
{
$.ajax({
url: url,
type: "POST",
dataType: 'json',
data: data,
processData: false,
contentType:false,
success: function (data) {
if (data.result) {
animateStatus("success", data.message, target);
msg = true;
}
else {
animateStatus("fail", data.message, target);
msg = false;
}
},
error:
function (data) {
animateStatus("fail", data.message, target);
msg = false;
}
});
}
这是我的控制器部分
[HttpPost]
public JsonResult UploadSlider()
{
bool valid = false;
bool val = false;
if (Request.Files.Count > 0)
{
valid = true;
}
else
{
return Json(new { result = false, message = "Something went wrong! Please try again!" });
}
if (valid)
{
List<string> fil = new List<string>();
foreach (HttpPostedFileBase f in Request.Files)
{
HttpPostedFileBase file = f; //Uploaded file
string fileName = file.FileName;
fil.Add("./Images/Galllery/" + fileName);
System.IO.Stream fileContent = file.InputStream;
file.SaveAs(Server.MapPath("~/Images/Gallery/") + fileName);
}
using (var context = new MCBConnectionString())
{
foreach (string path in fil)
{
tbl_slider slider = new tbl_slider();
slider.slurl = path;
slider.slalt = "";
context.tbl_slider.Add(slider);
context.SaveChanges();
val = true;
}
}
if (val)
{
return Json(new { result = true, message = "Uploaded video successfully." });
}
else
{
return Json(new { result = false, message = "Could not upload video. Please try again!" });
}
}
return Json(new { result = false, message = "Could not upload video. Please try again!" });
}
当我调试和检查 Request.Files.Count 时,它将始终为零。是否有任何替代解决方法,或者我在 post 处理文件时是否犯了任何错误。我已经关注了thislink并根据自己的需要进行了修改
而不是:
$.each($(fileInput).get(0).files, function (index, value) {
formdata.append($(this).attr('name'), $(this));
});
您可能会使用:
$.each($(fileInput).get(0).files, function (index, value) {
formdata.append(value.name, value);
});
主要区别在于,使用您的方法,Content-Disposition 部分不包含 filename
,因此 ASP.NET 无法将其识别为文件内容:
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO
Content-Disposition: form-data; name="foo.png"
[object Object]
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO
Content-Disposition: form-data; name="bar.png"
[object Object]
------WebKitFormBoundaryZxwCwBC0O8Q3hOAO--
按照我的方法,请求将如下所示:
------WebKitFormBoundary1ERBVX0wzdVczcR0
Content-Disposition: form-data; name="foo.png"; filename="foo.png"
Content-Type: imag/png
[object Object]
------WebKitFormBoundary1ERBVX0wzdVczcR0
Content-Disposition: form-data; name="bar.png"; filename="bar.png"
Content-Type: image/png
[object Object]
------WebKitFormBoundary1ERBVX0wzdVczcR0--
现在你可以看到实际的区别了。在第一种情况下,您没有 filename
也没有 Content-Type
文件,ASP.NET 只是将这些元素视为标准形式的发布数据而不是文件。
此外,您可以考虑将其替换为一些通用名称,而不是使用实际文件名 name
:
$.each($(fileInput).get(0).files, function (index, value) {
formdata.append('sliderFiles', value);
});
现在您可以通过使用 List<HttpPostedFileBase>
参数而不是使用 Request.Files
:
[HttpPost]
public ActionResult UploadSlider(List<HttpPostedFileBase> sliderFiles)
{
...
}
关于您的代码的另一个评论是 HTML5 FormData
在顺序浏览器中不可用,您的代码将默默地失败。如果您需要支持旧版浏览器,您可能需要通过测试浏览器的功能来执行渐进式增强,如果浏览器不支持 FormData:
$("#" + form).on("submit", function (e) {
if(window.FormData === undefined) {
// The browser doesn't support uploading files with AJAX
// falling back to standard form upload
} else {
// The browser supports uploading files with AJAX =>
// we prevent the default form POST and use AJAX instead
e.preventDefault();
...
}
});