Handle file download from ajax post

前端 未结 20 2597
心在旅途
心在旅途 2020-11-21 05:46

I have a javascript app that sends ajax POST requests to a certain URL. Response might be a JSON string or it might be a file (as an attachment). I can easily detect Content

相关标签:
20条回答
  • 2020-11-21 06:11

    Here is how I got this working https://stackoverflow.com/a/27563953/2845977

    $.ajax({
      url: '<URL_TO_FILE>',
      success: function(data) {
        var blob=new Blob([data]);
        var link=document.createElement('a');
        link.href=window.URL.createObjectURL(blob);
        link.download="<FILENAME_TO_SAVE_WITH_EXTENSION>";
        link.click();
      }
    });

    Updated answer using download.js

    $.ajax({
      url: '<URL_TO_FILE>',
      success: download.bind(true, "<FILENAME_TO_SAVE_WITH_EXTENSION>", "<FILE_MIME_TYPE>")
    });

    0 讨论(0)
  • 2020-11-21 06:11

    Here is my solution using a temporary hidden form.

    //Create an hidden form
    var form = $('<form>', {'method': 'POST', 'action': this.href}).hide();
    
    //Add params
    var params = { ...your params... };
    $.each(params, function (k, v) {
        form.append($('<input>', {'type': 'hidden', 'name': k, 'value': v}));
    });
    
    //Make it part of the document and submit
    $('body').append(form);
    form.submit();
    
    //Clean up
    form.remove();
    

    Note that I massively use JQuery but you can do the same with native JS.

    0 讨论(0)
  • 2020-11-21 06:12

    Create a form, use the POST method, submit the form - there's no need for an iframe. When the server page responds to the request, write a response header for the mime type of the file, and it will present a download dialog - I've done this a number of times.

    You want content-type of application/download - just search for how to provide a download for whatever language you're using.

    0 讨论(0)
  • 2020-11-21 06:14

    Here is my solution, gathered from different sources: Server side implementation :

        String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        // Set headers
        response.setHeader("content-disposition", "attachment; filename =" + fileName);
        response.setContentType(contentType);
        // Copy file to output stream
        ServletOutputStream servletOutputStream = response.getOutputStream();
        try (InputStream inputStream = new FileInputStream(file)) {
            IOUtils.copy(inputStream, servletOutputStream);
        } finally {
            servletOutputStream.flush();
            Utils.closeQuitely(servletOutputStream);
            fileToDownload = null;
        }
    

    Client side implementation (using jquery):

    $.ajax({
    type: 'POST',
    contentType: 'application/json',
        url: <download file 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();
        }
    });   
    
    0 讨论(0)
  • 2020-11-21 06:16

    If response is an Array Buffer, try this under onsuccess event in Ajax:

     if (event.data instanceof ArrayBuffer) {
              var binary = '';
              var bytes = new Uint8Array(event.data);
              for (var i = 0; i < bytes.byteLength; i++) {
                  binary += String.fromCharCode(bytes[i])
              }
              $("#some_id").append("<li><img src=\"data:image/png;base64," + window.btoa(binary) + "\"/></span></li>");
              return;
          }
    
    • where event.data is response received in success function of xhr event.
    0 讨论(0)
  • 2020-11-21 06:17

    For those looking a more modern approach, you can use the fetch API. The following example shows how to download a spreadsheet file. It is easily done with the following code.

    fetch(url, {
        body: JSON.stringify(data),
        method: 'POST',
        headers: {
            'Content-Type': 'application/json; charset=utf-8'
        },
    })
    .then(response => response.blob())
    .then(response => {
        const blob = new Blob([response], {type: 'application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
        const downloadUrl = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = downloadUrl;
        a.download = "file.xlsx";
        document.body.appendChild(a);
        a.click();
    })
    

    I believe this approach to be much easier to understand than other XMLHttpRequest solutions. Also, it has a similar syntax to the jQuery approach, without the need to add any additional libraries.

    Of course, I would advise checking to which browser you are developing, since this new approach won't work on IE. You can find the full browser compatibility list on the following [link][1].

    Important: In this example I am sending a JSON request to a server listening on the given url. This url must be set, on my example I am assuming you know this part. Also, consider the headers needed for your request to work. Since I am sending a JSON, I must add the Content-Type header and set it to application/json; charset=utf-8, as to let the server know the type of request it will receive.

    0 讨论(0)
提交回复
热议问题