在没有ajax调用的情况下使用带有@HTML.BeginForm的formdata append

Posted

技术标签:

【中文标题】在没有ajax调用的情况下使用带有@HTML.BeginForm的formdata append【英文标题】:Use formdata append with @HTML.BeginForm without ajax call 【发布时间】:2018-10-18 07:35:43 【问题描述】:

我想要实现的是将文件附加到我从带有 javascript 的拖放字段中获得的发布请求中。 问题是,我不想读取所有输入字段并通过 ajax 调用发布数据,我想使用来自@html.BeginForm 的默认提交方法。 当我这样做时,multipart 并不真正包含该文件。

(注意:当我只是提交文件或手动读取所有输入字段并使用单独的 ajax 提交时,它可以工作。)

我的代码: 拖放js:

var file;
var isDragged = false;
var formData;
function dropHandler(ev) 
    isDragged = true;
    ev.preventDefault();
    // Use DataTransfer interface to access the file(s)
    for (var i = 0; i < ev.dataTransfer.files.length; i++) 
        file = ev.dataTransfer.files[i];

        formData = new FormData($("#form"));
        formData.append("File.PayLoad", file);
        formData.append("File.FileMetadataId", $('#File_FileMetadataId').val())
        formData.append("File.FileObjectId", $('#File_FileObjectId').val())      
   

HTML:

  @using (Html.BeginForm("Edit", "DocumentTemplates", FormMethod.Post, new  role = "form", enctype = "multipart/form-data", id = "form" ))
    
     @Html.AntiForgeryToken()
     <div class="row">
         <div class="col-xs-4">
             @Html.LabelFor(model => model.Language)
         </div>
         <div class="col-xs-8">
             @Html.HiddenFor(model => model.Language) @Html.DisplayFor(model => model.Language)
         </div>
     </div>
     <div class="row">
         <div class="col-xs-8">
             @Html.TextBoxFor(model => model.File.Payload, new  type = "file", @id = "browseFile", ondrop = "dropHandler(event);", ondragover = "dragOverHandler(event);" ) 
             @Html.ValidationMessageFor(model => model.File.Payload, null, new  @class = "text-danger" ) or Drag & Drop a File.
         </div>
     </div>
    

在 Fiddler 中使用空文件名请求:

-----------------------------7e27b381715d4
Content-Disposition: form-data; name="File.FileMetadataId"

44
-----------------------------7e27b381715d4
Content-Disposition: form-data; name="File.FileObjectId"

44
-----------------------------7e27b381715d4
Content-Disposition: form-data; name="File.Payload"; filename=""
Content-Type: application/octet-stream


-----------------------------7e27b381715d4--

更新: 我发现,您可以从文件输入中覆盖文件,但只能在 Chrome 中。由于我需要它在 IE 11 上工作,这对我没有帮助,但也许它可以帮助其他人。您不需要附加所有表单字段,只需将输入类型文件设置为您放置的文件并提交......

【问题讨论】:

您确定 type="file" 存在于生成的 HTML 中吗? 是的,渲染时有一个典型的文件输入框,带有“浏览..”按钮 【参考方案1】:

你有几个问题。问题之一是下面的代码。您在代码中遗漏了一个

如果你像下面这样写,最后一个值只是存储在file 中,这是不正确的。

for (var i = 0; i < ev.dataTransfer.files.length; i++) 
        file = ev.dataTransfer.files[i];
 // missing 

如果你像下面这样写,最后一个值只是存储在formData 中,这是不正确的。

function dropHandler(ev) 
    isDragged = true;
    ev.preventDefault();
    // Use DataTransfer interface to access the file(s)
    for (var i = 0; i < ev.dataTransfer.files.length; i++) 
        file = ev.dataTransfer.files[i];

    formData = new FormData($("#form"));
    formData.append("File.PayLoad", file);
    formData.append("File.FileMetadataId", $('#File_FileMetadataId').val());
    formData.append("File.FileObjectId", $('#File_FileObjectId').val());    
   
 // missing 

第二个问题是ev.dataTransfer.files。正如您在File drag and drop 中看到的,最好检查ev.dataTransfer.items,有时它有您的文件,而ev.dataTransfer.files 是空的。

最后,你可以这样做:

function dropHandler(ev) 
    isDragged = true;
    ev.preventDefault();    

    formData = new FormData($("#form"));

    if (ev.dataTransfer.items) 
        // Use DataTransferItemList interface to access the file(s)
        for (var i = 0; i < ev.dataTransfer.items.length; i++) 
            // If dropped items aren't files, reject them
            if (ev.dataTransfer.items[i].kind === 'file') 
                var file = ev.dataTransfer.items[i].getAsFile();
                formData.append("File.PayLoad" + i, file);
            
        
     else 
        // Use DataTransfer interface to access the file(s)
        for (var i = 0; i < ev.dataTransfer.files.length; i++) 
            file = ev.dataTransfer.files[i];
            formData.append("File.PayLoad" + i, file);
        
    

【讨论】:

缺少的大括号只在这里,不在我的代码中,对此感到抱歉。该文件也不是问题,因为当我通过 ajax 调用直接提交它而没有其他表单时它可以工作。

以上是关于在没有ajax调用的情况下使用带有@HTML.BeginForm的formdata append的主要内容,如果未能解决你的问题,请参考以下文章

Ajax 将带有两个数组的 JSON 对象发送到一个 servlet 并在没有 jQuery 的情况下在 java servlet 中解析

带有 jQ​​uery Ajax 的 JWT 令牌

如何将带有附加数据的 FormData 文件发送到 asp.net web api ajax 调用

如何在没有 ajax 调用的情况下在 window.location 中传递一个数组

AJAX 调用在没有明显原因的情况下破坏会话

带有 jQ​​uery Ajax 调用的 MVC 无法正确绑定空数组/可枚举