Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use formdata append with @HTML.BeginForm without ajax call

What I'm trying to achieve is to append a file to a post request which I got from a drag & drop field with javascript. The problem is, I don't want to read all input fields and post the data by ajax call, I want to use the default submit method from @HTML.BeginForm. When I do this, the multipart doesn't really contain the file.

(Attention: It works when I just submit the file or when I read all input fields manually and submit with a separate ajax.)

My code: Drag&Drop 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>
    }

Request in Fiddler with empty Filename:

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

UPDATE: I found out, you can overwrite the files from a file input, but only in Chrome. Since I need it to work on IE 11, this doesn't help me, but maybe it helps someone else. You don't need to append all the form fields, but just set the input type file to your dropped file and submit…

like image 800
Gwny Avatar asked May 08 '18 11:05

Gwny


1 Answers

You have several problems there. One of the problems is code below. You missed one } in your code.

If you put it like below, the last value just store in file that is incorrect.

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

If you put it like below, the last value just store in formData that is incorrect.

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 }

Second problem is ev.dataTransfer.files. As you can see in File drag and drop, it's better to check ev.dataTransfer.items and sometimes it has your files and ev.dataTransfer.files is empty.

Finally, you can do it like this:

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);
        }
    }
}
like image 152
Ali Soltani Avatar answered Sep 28 '22 04:09

Ali Soltani