通过Spring MVC使用ajax()POST请求下载文件

时间:2012-11-22 19:35:09

标签: javascript jquery spring-mvc

我尝试下载文件。该操作由ajax()发布请求触发。请求以json格式将数据发送到控制器。控制器生成文件(字节)并将其发回。

java脚本:

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

控制器:

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

问题:
*浏览器应该打开一个下载框,但它不会发生 *响应在错误:ajax函数部分处理(但http状态正常)

那么我错了什么或者做到这一点的正确方法是什么?

5 个答案:

答案 0 :(得分:15)

只需发送回复的文件网址,然后在success回调中“访问”该文件。

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来说明客户端在哪里获取文件。

因此,您的服务器将发送带有JSON的响应,如

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

答案 1 :(得分:6)

@ will824正如你所问,我会发布自己的解决方案。

我在控制器中使用了一种解决方法,并将文件临时保存在文件系统(/ tmp)中。我分两步拆分了这个功能。创建和下载。 这不是很好,但对我来说已经足够了。

Controller(创建文件,将保存在服务器文件系统中):

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

}

控制器(下载文件):

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

答案 2 :(得分:4)

如果您想要没有更改网址的下载文件,可以使用ajax以编程方式调用form.submit()。

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


控制器:



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


答案 3 :(得分:2)

正如评论所说,你不能用ajax调用来做,但你可以用普通的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;
}

请注意${pageContext.request.contextPath}的使用,优先于<%=request.getContextPath()%>

答案 4 :(得分:0)

Ajax不会帮助您尝试隐藏表单方法

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

通过表单字段传递json 点击下载按钮提交表单

$(&#39;#formid&#39)。提交();

然后在服务器端

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

 ServletOutputStream out = res.getOutputStream();

写入ouput流然后关闭或刷新

如果您通过post 更新postize in server.xml

发送大量数据