jQuery Ajax Upload-Datei in asp.net mvc

77

Ich habe eine Datei in meiner Ansicht

<form id="upload" enctype="multipart/form-data">
   <input type="file" name="fileUpload" id="fileUpload" size="23" />
</form>

und eine Ajax-Anfrage

$.ajax({
    url: '<%=Url.Action("JsonSave","Survey")  %>',
    dataType: 'json',
    processData: false,
    contentType: "multipart/mixed",
    data: {
        Id: selectedRow.Id,
        Value: 'some date was added by the user here :))'
    },
    cache: false,
    success: function (data) {}
});

Die Request.Files enthalten jedoch keine Datei . Was ist los mit der Ajax-Anfrage?

CoffeeCode
quelle
json kann solche Dateien nicht hochladen. Verwenden Sie besser das Standard-Upload-Verhalten des Browsers.
Hogan

Antworten:

135

Laden Sie Dateien mit AJAX in ASP.Net MVC hoch

Die Dinge haben sich seit HTML5 geändert

JavaScript

document.getElementById('uploader').onsubmit = function () {
    var formdata = new FormData(); //FormData object
    var fileInput = document.getElementById('fileInput');
    //Iterating through each files selected in fileInput
    for (i = 0; i < fileInput.files.length; i++) {
        //Appending each file to FormData object
        formdata.append(fileInput.files[i].name, fileInput.files[i]);
    }
    //Creating an XMLHttpRequest and sending
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/Home/Upload');
    xhr.send(formdata);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            alert(xhr.responseText);
        }
    }
    return false;
}   

Regler

public JsonResult Upload()
{
    for (int i = 0; i < Request.Files.Count; i++)
    {
        HttpPostedFileBase file = Request.Files[i]; //Uploaded file
        //Use the following properties to get file's name, size and MIMEType
        int fileSize = file.ContentLength;
        string fileName = file.FileName;
        string mimeType = file.ContentType;
        System.IO.Stream fileContent = file.InputStream;
        //To save file, use SaveAs method
        file.SaveAs(Server.MapPath("~/")+ fileName ); //File will be saved in application root
    }
    return Json("Uploaded " + Request.Files.Count + " files");
}

EDIT : Der HTML

<form id="uploader">
    <input id="fileInput" type="file" multiple>
    <input type="submit" value="Upload file" />
</form>
Ajeesh M.
quelle
1
Können Sie den Code für die Ansicht hinzufügen? das HTML .. zu dieser Antwort.
Eric Bishard
Schöner Blog Ajeesh! Vielen Dank!
Eric Bishard
1
Hallo, gibt es eine Möglichkeit, die hochgeladenen Dateien in ein Modell zu binden?
Yorro
Dies funktioniert im IE nicht. Der IE übergibt den vollständigen lokalen Pfad des Benutzers im Parameter file.FileName. Daher müssen Sie Path.GetFileName (file.FileName) verwenden, um sicher zu sein. Ansonsten fantastische Antwort. Große Hilfe, danke.
Lee Richardson
Links in dieser Antwort (und der andere im Kommentar) sind defekt
DLeh
41

Das Hochladen von AJAX-Dateien ist jetzt möglich, indem ein FormDataObjekt an die dataEigenschaft von übergeben wird$.ajax Anforderung übergeben wird.

Da das OP speziell nach einer jQuery-Implementierung gefragt hat, können Sie Folgendes tun:

<form id="upload" enctype="multipart/form-data" action="@Url.Action("JsonSave", "Survey")" method="POST">
    <input type="file" name="fileUpload" id="fileUpload" size="23" /><br />
    <button>Upload!</button>
</form>
$('#upload').submit(function(e) {
    e.preventDefault(); // stop the standard form submission

    $.ajax({
        url: this.action,
        type: this.method,
        data: new FormData(this),
        cache: false,
        contentType: false,
        processData: false,
        success: function (data) {
            console.log(data.UploadedFileCount + ' file(s) uploaded successfully');
        },
        error: function(xhr, error, status) {
            console.log(error, status);
        }
    });
});
public JsonResult Survey()
{
    for (int i = 0; i < Request.Files.Count; i++)
    {
        var file = Request.Files[i];
        // save file as required here...
    }
    return Json(new { UploadedFileCount = Request.Files.Count });
}

Weitere Informationen zu FormData bei MDN

Rory McCrossan
quelle
7
Schön. Vielen Dank! Beste Antwort, die ich auf MEHRERE Fragen gefunden habe.
Jess
1
Kam hier speziell auf der Suche nach einer jQuery-Lösung und war ein wenig enttäuscht zu sehen, dass die als Beantwortet markierte Antwort nur Vanille-JavaScript verwendete. Ihre Lösung ist großartig und funktioniert sehr gut für mich. Vielen Dank :)
Joshua K
Beachten Sie, dass, wenn Sie keine Datei auswählen, immer noch eine einzelne Datei im Array angezeigt wird, mit ContentLength = 0
Savage
@Savage: getestet im Jahr 2020 / chrome / asp net core mvc: Datei ist null, wenn Sie nichts auswählen. Wie auch immer, die Antwort ist eine wirklich saubere Integration des Hochladens von Dateien mit Rasiermesser und MVC-Controller
christophe.chapron
4

Sie können keine Dateien über Ajax hochladen. Sie müssen einen iFrame oder einen anderen Trick verwenden, um ein vollständiges Postback durchzuführen. Dies ist hauptsächlich auf Sicherheitsbedenken zurückzuführen.

Hier ist eine anständige Zusammenfassung, einschließlich eines Beispielprojekts mit SWFUpload und ASP.Net MVC von Steve Sanderson. Es ist das erste, was ich gelesen habe, damit dies mit Asp.Net MVC richtig funktioniert (ich war zu diesem Zeitpunkt auch neu bei MVC), hoffentlich ist es für Sie genauso hilfreich.

Nick Craver
quelle
13
Das ist nicht wahr; Sie können die Formulardaten über Ajax senden.
Josh M.
@ JoshM. Ja, aber Sie können keine Dateien über AJAX ohne eine externe Lösung senden.
Kehlan Krumme
8
@kehrk: Mit den neuen FormData- und File-Objekten in HTML5 können Sie tatsächlich Dateien über AJAX hochladen. Versuchen Sie Folgendes: developer.mozilla.org/en-US/docs/… .
jrista
1

Ich habe ein Beispiel wie dieses auf vuejs Version: v2.5.2

<form action="url" method="post" enctype="multipart/form-data">
    <div class="col-md-6">
        <input type="file" class="image_0" name="FilesFront" ref="FilesFront" />
    </div>
    <div class="col-md-6">
        <input type="file" class="image_1" name="FilesBack" ref="FilesBack" />
    </div>
</form>
<script>
Vue.component('v-bl-document', {
    template: '#document-item-template',
    props: ['doc'],
    data: function () {
        return {
            document: this.doc
        };
    },
    methods: {
        submit: function () {
            event.preventDefault();

            var data = new FormData();
            var _doc = this.document;
            Object.keys(_doc).forEach(function (key) {
                data.append(key, _doc[key]);
            });
            var _refs = this.$refs;
            Object.keys(_refs).forEach(function (key) {
                data.append(key, _refs[key].files[0]);
            });

            debugger;
            $.ajax({
                type: "POST",
                data: data,
                url: url,
                cache: false,
                contentType: false,
                processData: false,
                success: function (result) {
                    //do something
                },

            });
        }
    }
});
</script>
ddagsan
quelle
Verdammt noch mal, ich habe den größten Teil von 2 Tagen damit verbracht, mich mit diesem Problem zu beschäftigen, und hier ist eine Lösung. Ist es jedoch möglich, das Formular zu modellieren?
Marqueone
0

Wenn Sie ein Formular mit Ajax veröffentlichen, können Sie kein Bild mit der $ .ajax-Methode senden. Sie müssen die klassische xmlHttpobject-Methode zum Speichern des Bildes verwenden. Eine andere Alternative ist der Submit-Typ anstelle der Schaltfläche

Sandeep
quelle