【问题标题】:MVC Anti-forgery Token won't allow multiple file upload when posting through AJAXMVC Anti-forgery Token 在通过 AJAX 发布时不允许上传多个文件
【发布时间】:2019-06-30 19:16:58
【问题描述】:

我知道上传多个文件可以正常工作,因为当我注释掉 [ValidateAntiForgeryToken]我可以选择多个文件,它们将按预期上传而没有任何问题。

但是,当我将[ValidateAntiForgeryToken] 放回If I select 2 or more files 时,我得到了服务器500 status error,并且没有任何文件被上传。

另外,我将添加错误: Failed to load resource: the server responded with a status of 500 (Internal Server Error) 堆栈跟踪说它停止在 line 1 of Upload action

但是,如果我选择 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.

【问题讨论】:

  • 您只得到最后一个文件,因为所有文件都具有相同的文件名。它只是看起来像一个文件被上传(最后一个)。检查上传文件的大小,看看文件夹中的文件大小。
  • 对不起,我应该告诉你的。当我使用 [ValidateAntiforgeryToken] 选择多个文件时,我没有上传任何文件。只有当我选择1个文件时,我才会在相同的情况下上传它。我会更新帖子。 :)

标签: c# ajax model-view-controller csrf antiforgerytoken


【解决方案1】:

将这条线从循环中取出(放在循环的上方或下方):

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

append 将继续添加到提交给服务器的__RequestVerificationToken 值。一旦它被附加到一次(即,如果您选择了 2 个或更多文件),该值将不是有效的 XSRF 防伪令牌。然后它无法验证,因此您在服务器上收到错误。

【讨论】:

  • 天哪!我很抱歉——我现在没有注意到这一点感到很愚蠢。非常感谢 - 一双新的眼睛有很长的路要走:) 现在我理解了这个问题......我看到这个问题并没有反映实际问题。我对 S.O. 有点陌生。我该怎么办? >_
  • @LiudvikasTaluntis 很高兴它有帮助。就你的问题而言,没关系。您描述了您的问题,提供了必要的代码和重现步骤。不要管它。仅仅因为问题很明显(并且与您认为的不同)现在并不会使问题无效。
【解决方案2】:

也许你应该在循环之外设置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);
    }

【讨论】:

  • 感谢您注意到这一点。我认为那部分代码很好的假设对我不利>__
  • 我不知道 :) 也许将问题标记为已回答。也许其他人会通过多次追加__RequestVerificationToken来犯类似的错误。
  • 我明白了 :) 再次感谢您的帮助 - 如果不解决此问题,我不会离开家。 :D
猜你喜欢
  • 2017-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多