通过 AJAX 发帖时,MVC 防伪令牌不允许上传多个文件
MVC Anti-forgery Token won't allow multiple file upload when posting through AJAX
我知道上传多个文件没问题,因为,当我注释掉
[ValidateAntiForgeryToken]
我可以 select 多个文件,它们将按预期毫无问题地上传。
然而,当我将 [ValidateAntiForgeryToken]
放回 If I select 2 or more files
时,我得到服务器 500 status error
并且文件的 none 被上传。
此外,我将添加错误:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
堆栈跟踪表明它在 line 1 of Upload action
停止
但是,如果我 select 1 个文件,它会成功上传并且我得到 status code 200
。
我对此还是很陌生 - 我不知道哪里出了问题。感谢您对这个谜团的任何帮助。 :-)
这是我的控制器操作:
[HttpPost]
[ValidateAntiForgeryToken] // If I comment this out, everything works as intended
public ActionResult Upload()
{
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Some/FilePath"), fileName);
file.SaveAs(path);
}
return Json(new { success = true, responseText = "Success!" }, JsonRequestBehavior.AllowGet); //This is placeholder, I'll implement validation later
}
HTML:
@Html.TextBoxFor(model => model.file, new { type = "file", id = "file-upload", multiple="multiple" })
@Html.ValidationMessageFor(model => model.file, "", new { @class = "text-danger" })
<div id="selectedFiles"></div>
我构建了我的自定义文件阵列,因此我可以拥有一个奇特的删除文件功能。
这是我调用 UploadAjax
函数的方式:
var storedFiles = []; //this is what I pass to it.
$("#stupidTest").click(function () {
UploadAjax(storedFiles);
});
JQuery、AJAX。这是上传功能。
function UploadAjax(storedFilesArray) {
var formData = new FormData();
for (let i = 0; i < storedFilesArray.length; i++) {
let file = storedFilesArray[i];
formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.
formData.append("file-upload", file);
}
$.ajax({
type: "POST",
dataType: 'json',
cache: false,
url: '/Home/Upload',
data: formData,
contentType: false,
processData: false,
success: function (response) {
...
},
error: function (response) {
...
}
});
}
**Edit: Found that this happened at the same second my multiple file upload request failed**
System.Web.Mvc.HttpAntiForgeryException: The anti-forgery token could not be
decrypted. If this application is hosted by a Web Farm or cluster, ensure that
all machines are running the same version of ASP.NET Web Pages and that the
<machineKey> configuration specifies explicit encryption and validation keys.
AutoGenerate cannot be used in a cluster.
将这一行从循环中取出(放在循环的上方或下方):
formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.
append
将继续添加到提交给服务器的 __RequestVerificationToken
值。一旦它被附加到一次(即,如果您选择了 2 个或更多文件),该值将不是有效的 XSRF 防伪标记。然后它无法验证,因此您在服务器上收到错误。
也许你应该在循环外设置formData.append('__RequestVerificationToken', getToken());
?
var formData = new FormData();
formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.
for (let i = 0; i < storedFilesArray.length; i++) {
let file = storedFilesArray[i];
formData.append("file-upload", file);
}
我知道上传多个文件没问题,因为,当我注释掉
[ValidateAntiForgeryToken]
我可以 select 多个文件,它们将按预期毫无问题地上传。
然而,当我将 [ValidateAntiForgeryToken]
放回 If I select 2 or more files
时,我得到服务器 500 status error
并且文件的 none 被上传。
此外,我将添加错误:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
堆栈跟踪表明它在 line 1 of Upload action
但是,如果我 select 1 个文件,它会成功上传并且我得到 status code 200
。
我对此还是很陌生 - 我不知道哪里出了问题。感谢您对这个谜团的任何帮助。 :-)
这是我的控制器操作:
[HttpPost]
[ValidateAntiForgeryToken] // If I comment this out, everything works as intended
public ActionResult Upload()
{
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Some/FilePath"), fileName);
file.SaveAs(path);
}
return Json(new { success = true, responseText = "Success!" }, JsonRequestBehavior.AllowGet); //This is placeholder, I'll implement validation later
}
HTML:
@Html.TextBoxFor(model => model.file, new { type = "file", id = "file-upload", multiple="multiple" })
@Html.ValidationMessageFor(model => model.file, "", new { @class = "text-danger" })
<div id="selectedFiles"></div>
我构建了我的自定义文件阵列,因此我可以拥有一个奇特的删除文件功能。
这是我调用 UploadAjax
函数的方式:
var storedFiles = []; //this is what I pass to it.
$("#stupidTest").click(function () {
UploadAjax(storedFiles);
});
JQuery、AJAX。这是上传功能。
function UploadAjax(storedFilesArray) {
var formData = new FormData();
for (let i = 0; i < storedFilesArray.length; i++) {
let file = storedFilesArray[i];
formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.
formData.append("file-upload", file);
}
$.ajax({
type: "POST",
dataType: 'json',
cache: false,
url: '/Home/Upload',
data: formData,
contentType: false,
processData: false,
success: function (response) {
...
},
error: function (response) {
...
}
});
}
**Edit: Found that this happened at the same second my multiple file upload request failed**
System.Web.Mvc.HttpAntiForgeryException: The anti-forgery token could not be
decrypted. If this application is hosted by a Web Farm or cluster, ensure that
all machines are running the same version of ASP.NET Web Pages and that the
<machineKey> configuration specifies explicit encryption and validation keys.
AutoGenerate cannot be used in a cluster.
将这一行从循环中取出(放在循环的上方或下方):
formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.
append
将继续添加到提交给服务器的 __RequestVerificationToken
值。一旦它被附加到一次(即,如果您选择了 2 个或更多文件),该值将不是有效的 XSRF 防伪标记。然后它无法验证,因此您在服务器上收到错误。
也许你应该在循环外设置formData.append('__RequestVerificationToken', getToken());
?
var formData = new FormData();
formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.
for (let i = 0; i < storedFilesArray.length; i++) {
let file = storedFilesArray[i];
formData.append("file-upload", file);
}