Download file with ajax() POST request via Spring MVC

后端 未结 5 709
予麋鹿
予麋鹿 2020-12-06 11:24

I try to download a file. The action is triggered by ajax() POST request. The request sends data in JSON format to the controller. The controller gener

相关标签:
5条回答
  • 2020-12-06 11:44

    If you want download file without change URL, you can call form.submit() programmatically instead of using AJAX.

    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");
    

    Controller:

    [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");
    }
    
    0 讨论(0)
  • 2020-12-06 11:51

    Ajax is not going to help you try with hidden form approach

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

    pass you json through form field on click of of your download button submit form

    $('#formid').submit();

    then in server side

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

    write on ouput stream then close or flush

    if you are sending large data through post update postsize in server.xml

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

    As the comments said you can't do it with an ajax call, but you can do it with plain Javascript.

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

    Note the use of ${pageContext.request.contextPath}, which is preferred over <%=request.getContextPath()%>.

    0 讨论(0)
  • 2020-12-06 12:00

    @will824 As you ask I'll post my own solution.

    I used a workaround in controller and save the file temporarily in the files ystem (/tmp). I split up the function in 2 steps. Creating and downloading. This is not very nice but good enough for me.

    Controller (creates a file, will be saved on the server file system):

    @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;
    
    }
    

    Controller (downloads a file):

    @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 = '${pageContext.request.contextPath}/licenses/downloadFile/'
                        + data;
            },
            error : function(xhr, ajaxOptions, thrownError) {
                // error handling
            }
        });
    }
    
    0 讨论(0)
  • 2020-12-06 12:05

    Just send a URL of file in response and then "visit" it in your success callback.

    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 should be set in response by server to say client where to get the file.

    So your server will send a response with JSON like

    {
        "fileUrl": "http://mysite.com/files/0123456789"
    }
    
    0 讨论(0)
提交回复
热议问题