简体   繁体   English

通过AJAX发布时,MVC防伪令牌不允许上传多个文件

[英]MVC Anti-forgery Token won't allow multiple file upload when posting through AJAX

I know that uploading multiple files works fine, because, when I comment out [ValidateAntiForgeryToken] I can select multiple files and they will get uploaded without any issue all as intended. 我知道上传多个文件效果很好,因为当我注释掉[ValidateAntiForgeryToken]我可以选择多个文件,并且它们将被上传而没有任何预期的问题。

However when I put [ValidateAntiForgeryToken] back If I select 2 or more files , I get server 500 status error and none of the files get uploaded. 但是,当我放回[ValidateAntiForgeryToken] If I select 2 or more files ,则会收到服务器500 status error并且没有文件上传。

Additionally I'll add the error: Failed to load resource: the server responded with a status of 500 (Internal Server Error) the stack trace says it stopped on line 1 of Upload action 此外,我还会添加错误: Failed to load resource: the server responded with a status of 500 (Internal Server Error) ,堆栈跟踪表明它已停止在上line 1 of Upload action

However, if I select 1 file, it gets uploaded successfully and I get status code 200 . 但是,如果我选择1个文件,则文件上传成功,并且status code 200

I'm still fairly new to this - I can't tell what's wrong. 我对此还很陌生-我不知道怎么了。 I appreciate any help on this enigma. 我感谢对这个谜的任何帮助。 :-) :-)

This is my controller action: 这是我的控制器动作:

[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
}

The HTML: 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>

I build my custom file Array, so I could have a fancy remove file feature. 我构建了自定义文件Array,因此可以使用精美的删除文件功能。 This is my how I call the UploadAjax function: 这是我如何调用UploadAjax函数:

var storedFiles = [];    //this is what I pass to it.

$("#stupidTest").click(function () {
    UploadAjax(storedFiles);
});

JQuery, AJAX. jQuery,AJAX。 This is the upload function. 这是上传功能。

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.

Take this line out of the loop (and put it above or below the loop): 将此行移出循环(并将其置于循环的上方或下方):

formData.append('__RequestVerificationToken', getToken()); //appends the value to the formData.

append will keep adding on to the __RequestVerificationToken value that gets submitted to the server. append将继续添加到提交给服务器的__RequestVerificationToken值上。 Once it has been appended to once (ie. if you've selected 2 or more files), the value won't be a valid XSRF anti-forgery token. 一旦将其附加到一次(即,如果您选择了2个或更多文件),则该值将不是有效的XSRF防伪令牌。 And then it fails to validate and thus you get an error on the server. 然后它无法验证,因此您在服务器上收到错误。

Maybe yuo should set formData.append('__RequestVerificationToken', getToken()); 也许您应该设置formData.append('__RequestVerificationToken', getToken()); outside the cycle? 周期外?

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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM