486 Stimmen

Datei-Download von Ajax-Post verarbeiten

Ich habe eine JavaScript-App, die Ajax POST-Anforderungen an eine bestimmte URL sendet. Die Antwort kann ein JSON-String sein oder es kann sich um eine Datei handeln (als Anhang). Ich kann problemlos Content-Type und Content-Disposition in meinem Ajax-Aufruf erkennen, aber sobald ich feststelle, dass die Antwort eine Datei enthält, wie kann ich dem Client anbieten, sie herunterzuladen? Ich habe eine Reihe ähnlicher Threads hier gelesen, aber keiner von ihnen liefert die Antwort, nach der ich suche.

Bitte, bitte, bitte posten Sie keine Antworten, die vorschlagen, dass ich Ajax nicht verwenden sollte oder den Browser umleiten sollte, denn das ist keine Option. Die Verwendung eines einfachen HTML-Formulars ist ebenfalls keine Option. Was ich brauche, ist, dem Client einen Download-Dialog anzuzeigen. Kann dies gemacht werden und wie?

3voto

KurtPreston Punkte 983

Wie andere bereits gesagt haben, können Sie ein Formular erstellen und über eine POST-Anfrage zum Download einreichen. Sie müssen dies jedoch nicht manuell tun.

Eine wirklich einfache Bibliothek, um genau dies zu tun, ist jquery.redirect. Es bietet eine API, die der Standardmethode jQuery.post ähnelt:

$.redirect(url, [values, [method, [target]]])

3voto

Jairo Miranda Punkte 31

Dies ist eine 3 Jahre alte Frage, aber heute hatte ich das gleiche Problem. Ich habe mir deine bearbeitete Lösung angesehen, aber ich denke, dass dies die Leistung beeinträchtigen kann, da es eine doppelte Anfrage machen muss. Wenn also jemand eine andere Lösung benötigt, die nicht bedeutet, den Service zweimal aufzurufen, dann ist das der Weg, den ich gegangen bin:

Dieses Formular wird nur verwendet, um den Service aufzurufen und nicht window.location() zu verwenden. Danach müssen Sie einfach ein Formular mit jQuery absenden, um den Service aufzurufen und die Datei zu erhalten. Es ist ziemlich einfach, aber auf diese Weise können Sie einen Download mit einem POST durchführen. Ich weiß, dass dies einfacher sein könnte, wenn der Service, den Sie aufrufen, ein GET ist, aber das ist nicht mein Fall.

1voto

Samantha Adrichem Punkte 718

Sehen: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ es wird eine Blob als Antwort zurückgeben, die dann in filesaver eingefügt werden kann

1voto

ticky Punkte 353

Im Folgenden finden Sie meine Lösung zum Herunterladen mehrerer Dateien, abhängig von einer Liste, die aus einigen IDs besteht und nach dem Durchsuchen der Datenbank werden die Dateien bestimmt und zum Download bereit sein - falls diese existieren. Ich rufe die C# MVC-Aktion für jede Datei mit Hilfe von Ajax auf.

Und ja, wie andere gesagt haben, es ist möglich, es mit jQuery Ajax zu tun. Ich habe es mit Ajax-Erfolg gemacht und sende immer eine Antwort 200.

Also, das ist der Schlüssel:

  success: function (data, textStatus, xhr) {

Und das ist mein Code:

var i = 0;
var max = 0;
function DownloadMultipleFiles() {
            if ($(".dataTables_scrollBody>tr.selected").length > 0) {
                var list = [];
                showPreloader();
                $(".dataTables_scrollBody>tr.selected").each(function (e) {
                    var element = $(this);
                    var orderid = element.data("orderid");
                    var iscustom = element.data("iscustom");
                    var orderlineid = element.data("orderlineid");
                    var folderPath = "";
                    var fileName = "";

                    list.push({ orderId: orderid, isCustomOrderLine: iscustom, orderLineId: orderlineid, folderPath: folderPath, fileName: fileName });
                });
                i = 0;
                max = list.length;
                DownloadFile(list);
            }
        }

Dann rufe ich auf:

function DownloadFile(list) {
        $.ajax({
            url: '@Url.Action("OpenFile","OrderLines")',
            type: "post",
            data: list[i],
            xhrFields: {
                responseType: 'blob'
            },
            beforeSend: function (xhr) {
                xhr.setRequestHeader("RequestVerificationToken",
                    $('input:hidden[name="__RequestVerificationToken"]').val());

            },
            success: function (data, textStatus, xhr) {
                // Überprüfen auf einen Dateinamen
                var filename = "";
                var disposition = xhr.getResponseHeader('Content-Disposition');
                if (disposition && disposition.indexOf('attachment') !== -1) {
                    var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                    var matches = filenameRegex.exec(disposition);
                    if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
                    var a = document.createElement('a');
                    var url = window.URL.createObjectURL(data);
                    a.href = url;
                    a.download = filename;
                    document.body.append(a);
                    a.click();
                    a.remove();
                    window.URL.revokeObjectURL(url);
                }
                else {
                    getErrorToastMessage("Produktionsdatei für Auftragszeile " + list[i].orderLineId + " existiert nicht");
                }
                i = i + 1;
                if (i < max) {
                    DownloadFile(list);
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {

            },
            complete: function () {
                if(i===max)
                hidePreloader();
            }
        });
    }

C# MVC:

 [HttpPost]
 [ValidateAntiForgeryToken]
public IActionResult OpenFile(OrderLineSimpleModel model)
        {
            byte[] file = null;

            try
            {
                if (model != null)
                {
                    // Code zum Abrufen der Datei von der API - Teil fehlt hier, da nicht für dieses Beispiel wichtig
                    file = apiHandler.Get(downloadApiUrl, token);

                    var contentDispositionHeader = new System.Net.Mime.ContentDisposition
                    {
                        Inline = true,
                        FileName = fileName
                    };
                    //    Response.Headers.Add("Content-Disposition", contentDispositionHeader.ToString() + "; attachment");
                    Response.Headers.Add("Content-Type", "application/pdf");
                    Response.Headers.Add("Content-Disposition", "attachment; filename=" + fileName);
                    Response.Headers.Add("Content-Transfer-Encoding", "binary");
                    Response.Headers.Add("Content-Length", file.Length.ToString());

                }
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, "Fehler beim Abrufen von PDF", null);
                return Ok();
            }

            return File(file, System.Net.Mime.MediaTypeNames.Application.Pdf);
        }

Solange Sie eine Antwort 200 zurückgeben, kann der Erfolg in Ajax damit arbeiten. Sie können überprüfen, ob die Datei tatsächlich existiert oder nicht, da die Zeile unten in diesem Fall falsch wäre, und Sie den Benutzer darüber informieren können:

 if (disposition && disposition.indexOf('attachment') !== -1) {

1voto

Dvs Prajapati Punkte 11

Hier ist meine Lösung, die aus verschiedenen Quellen gesammelt wurde: Serverseitige Implementierung :

    String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
    // Setze Header
    response.setHeader("content-disposition", "attachment; filename =" + fileName);
    response.setContentType(contentType);
    // Kopiere Datei in Ausgabestrom
    ServletOutputStream servletOutputStream = response.getOutputStream();
    try (InputStream inputStream = new FileInputStream(file)) {
        IOUtils.copy(inputStream, servletOutputStream);
    } finally {
        servletOutputStream.flush();
        Utils.closeQuitely(servletOutputStream);
        fileToDownload = null;
    }

Clientseitige Implementierung (mit jQuery):

$.ajax({
type: 'POST',
contentType: 'application/json',
    url: ,
    data: JSON.stringify(postObject),
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert(errorThrown);
    },
    success: function(message, textStatus, response) {
       var header = response.getResponseHeader('Content-Disposition');
       var fileName = header.split("=")[1];
       var blob = new Blob([message]);
       var link = document.createElement('a');
       link.href = window.URL.createObjectURL(blob);
       link.download = fileName;
       link.click();
    }
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X