Datei mit ajax() POST-Anfrage über Spring MVC herunterladen

Lesezeit: 6 Minuten

Datei mit ajax POST Anfrage uber Spring MVC herunterladen
derlinuxer

Ich versuche eine Datei herunterzuladen. Die Aktion wird ausgelöst durch ajax() POST-Anfrage. Die Anfrage wird gesendet Daten im JSON-Format an den Controller. Die Steuerung generiert die Datei (Bytes) und sendet sie zurück.

JavaScript:

function getLicenseFile() {
    $.ajax({
        type: 'POST',
        url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
        dataType: 'json',
        contentType: 'application/json;charset=UTF-8',
        data: ko.mapping.toJSON(licenseModel),
        success: function (data) {
            console.log("in sucess")
        },
        error:function (xhr, ajaxOptions, thrownError){
            console.log("in error")
        } 
    });
}  

Regler:

@RequestMapping(value = "/licenses/rest/downloadLicenseFile", method = RequestMethod.POST)
@ResponseStatus(value=HttpStatus.OK)
@ResponseBody
public void createLicenseFile(@Valid @RequestBody License license, HttpServletResponse response) throws Exception {

    logger.debug("Contoller License in: "+ license);

    byte[] licensedata = licenseEncodeDefaultService.createLicenseFile(license);
    logger.debug("licenseData: " + new String(licensedata));

    response.setHeader("Content-Disposition", "attachment; filename="" + license.getCustomer() + ".license"");
    response.getOutputStream().write(licensedata);
    response.flushBuffer();
}

Problem

  • Der Browser sollte eine Download-Box öffnen, aber es passiert nicht
  • Die Antwort wird im Abschnitt error: der Ajax-Funktion behandelt (aber der HTTP-Status ist OK)

Was mache ich also falsch oder wie mache ich das richtig?

  • Du stellst ein dataType: 'json' aber eine Art Lizenzdatei senden? Ich glaube auch nicht, dass Sie Ajax verwenden können, um eine Datei herunterzuladen.

    – Musa

    22. November ’12 um 19:50

  • Der Versuch, eine Datei herunterzuladen, die mit Ajax im lokalen Verzeichnis gespeichert werden soll, kann nicht durchgeführt werden und ist viel mehr Code, als einfach nur auf die Datei-URL selbst zu verweisen

    – charlietfl

    22. November ’12 um 20:05


  • stackoverflow.com/questions/3613526/… könnte gut helfen

    – Robust

    22. November ’12 um 21:18 Uhr

  • Habe eine funktionierende Lösung gefunden: Wie kommuniziert man richtig. Soll ich meine Frage selbst beantworten???

    – derlinuxer

    23. November ’12 um 12:48


  • @derlinuxer Könnten Sie bitte die gefundene funktionierende Lösung teilen? Ich habe genau das gleiche Problem…

    – will824

    24. Juli ’13 um 23:02

Senden Sie einfach eine URL der Datei als Antwort und “besuchen” Sie sie dann in Ihrem success Ruf zurück.

function getLicenseFile() {
    $.ajax({
        type: 'POST',
        url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
        dataType: 'json',
        contentType: 'application/json;charset=UTF-8',
        data: ko.mapping.toJSON(licenseModel),
        success: function (data) {
            window.open(data.fileUrl);
            // or window.location.href = data.fileUrl;
        },
        error:function (xhr, ajaxOptions, thrownError) {
            console.log("in error");
        } 
    });
}

data.fileUrl sollte als Antwort vom Server gesetzt werden, um dem Client mitzuteilen, wo er die Datei erhält.

Ihr Server sendet also eine Antwort mit JSON wie

{
    "fileUrl": "http://mysite.com/files/0123456789"
}

  • hmm, normalerweise möchte ich die Datei nicht im Dateisystem auf der Serverseite speichern und auch eine saubere Download-URL haben. Generieren Sie einfach im Speicher und senden Sie die Bytes zurück. Aber ich muss es wirklich mit zwei Controller-Methoden tun. Die erste Methode generiert die Datei (speichert auf dem Server FS) und gibt den Dateinamen im JSON-Format zurück. Und die zweite Methode sendet die Dateidaten. So kann ich verhindern, dass ein sauberer Download-Pfad vorhanden ist. Ich werde das überprüfen.

    – derlinuxer

    23. November ’12 um 8:57

  • window.open(data.fileUrl); funktioniert nicht in einer asynchronen Umgebung. window.location.href = data.fileUrl; funktioniert perfekt!

    – lekant

    10. Dezember ’15 um 7:40


Datei mit ajax POST Anfrage uber Spring MVC herunterladen
derlinuxer

@will824 Wie Sie fragen, werde ich meine eigene Lösung posten.

Ich habe einen Workaround im Controller verwendet und die Datei vorübergehend im Dateisystem gespeichert (/tmp). Ich habe die Funktion in 2 Schritte aufgeteilt. Erstellen und herunterladen. Das ist nicht sehr schön, aber gut genug für mich.

Regler (erzeugt eine Datei, wird im Dateisystem des Servers gespeichert):

@RequestMapping(value = "/licenses/rest", method = RequestMethod.PUT)
@ResponseStatus(value=HttpStatus.OK)
@ResponseBody
public String createLicenseFile(@Valid @RequestBody License license) throws Exception {

    // create encrypted license file and send the name back to view
    String fileName =  licenseEncodeDefaultService.createLicenseFile(license);
    return fileName;

}

Regler (lädt eine Datei herunter):

@RequestMapping(value = "/licenses/downloadFile/{file}", method = RequestMethod.GET)
public void downloadLicenseFile(@PathVariable("file") String file, HttpServletResponse response) throws Exception {

    // create full filename and get input stream
    File licenseFile = new File ("/tmp/" + file);
    InputStream is = new FileInputStream(licenseFile);

    // set file as attached data and copy file data to response output stream
    response.setHeader("Content-Disposition", "attachment; filename="" + file + ".license"");
    FileCopyUtils.copy(is, response.getOutputStream());

    // delete file on server file system
    licenseFile.delete();

    // close stream and return to view
    response.flushBuffer();
}

JavaScript:

function getLicenseFile() {
    //console.log(ko.mapping.toJSON(licenseModel));
    $.ajax({
        type : 'PUT',
        url : '${pageContext.request.contextPath}/licenses/rest',
        dataType : 'text',
        contentType : 'application/json;charset=UTF-8',
        data : ko.mapping.toJSON(licenseModel),
        success : function(data) {
            window.location.href="https://stackoverflow.com/questions/13519058/${pageContext.request.contextPath}/licenses/downloadFile/"
                    + data;
        },
        error : function(xhr, ajaxOptions, thrownError) {
            // error handling
        }
    });
}

  • Vielen Dank für Ihre Antwort. Ich stimme zu, dass dies einen 1-Schritt-einfachen Prozess macht, um zweimal zum Server zu gehen, aber Ihre Lösung ist mehr oder weniger ähnlich der, die ich implementieren wollte, trotzdem durfte ich nicht zweimal zum Server gehen, also musste ich einfach gehen mit dem 1-Schritt-Aufruf, indem Sie ein unsichtbares Formular mit einem iframe verwenden, und akzeptieren Sie das Risiko, dass der Benutzer bei einem Fehler nie weiß, was passiert ist.

    – will824

    13. August ’13 um 16:54

1641935301 233 Datei mit ajax POST Anfrage uber Spring MVC herunterladen
Benutzer4532418

Wenn Sie die Datei herunterladen möchten, ohne die URL zu ändern, können Sie anrufen form.submit() programmatisch anstatt AJAX zu verwenden.

JavaScript:

function downloadFileUsingForm(url) { 
    var form = document.createElement("form");
    form.method = "post";
    form.action = url;
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
}
downloadFileUsingForm("/YourController/DownloadFile");

Regler:

[HttpPost]
public ActionResult DownloadFile()
{
    string content = "Some Values";
    byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(content);
    return File(bytes, System.Net.Mime.MediaTypeNames.Application.Octet, "file.txt");
}

  • Dies ist die beste Antwort, die ich für den Fall gefunden habe, an dem ich arbeite.

    – Poly

    12. Okt ’16 um 12:19

  • Als Anmerkung: die Frage bezog sich auf Spring MVC (daher Java), aber Ihr Controller-Beispiel ist in C# und .NETZ

    – informatik01

    13. November ’19 um 18:05

  • Beim Absenden eines Formulars wird kein JSON gesendet, das in den Fragen erforderlich war, daher ist diese Antwort falsch.

    – Plamen

    25. März ’21 um 19:52

Wie die Kommentare sagten, können Sie dies nicht mit einem Ajax-Aufruf tun, aber Sie können es mit einfachem Javascript tun.

function getLicenseFile() {
    var downloadUrl = "${pageContext.request.contextPath}/licenses/rest/downloadLicenseFile";
    // (optionally) provide the user with a message that the download is starting
    window.location.href = downloadUrl;
}

Beachten Sie die Verwendung von ${pageContext.request.contextPath}, was vorgezogen wird <%=request.getContextPath()%>.

Ajax wird Ihnen nicht helfen, den Ansatz mit versteckten Formularen auszuprobieren

<form action='../servletname' method='POST' id='formid'>
                <input type="hidden" value="" name="name" id='id'/>
                <input type="hidden" value=" " name="name"  id='id' />
            </form>

leiten Sie json durch das Formularfeld, wenn Sie auf Ihren Download-Button klicken Formular senden

$(‘#formid’).submit();

dann auf der Serverseite

response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment; filename=filnemae.fileformat");

 ServletOutputStream out = res.getOutputStream();

Schreibe in den Ausgabestream und schließe dann oder spüle sie aus

wenn Sie große Datenmengen per Post versenden postsize in server.xml aktualisieren

.

388860cookie-checkDatei mit ajax() POST-Anfrage über Spring MVC herunterladen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy