使用RESTful进行文件下载会导致HTTP 406不适用错误

时间:2015-10-20 18:22:49

标签: java spring rest extjs download

我正在尝试使用RESTful调用下载Excel文件。我认为它应该很简单,但我一直得到HTTP 406不适用Eror。这就是我的控制器方法:

@RequestMapping(value = "/gettemplate", method = RequestMethod.GET, produces = "application/vnd.ms-excel")
@ResponseBody
public Response getExcelTemplate() throws Exception {
    File templateFile = new File("TestFile.xlsx");
    ResponseBuilder builder = Response.ok(templateFile,"application/vnd.ms-excel");
    builder.header("Content-Disposition", "attachment; filename=\"" + templateFile.getName() + "\"" );
    return builder.build();
}

我已尝试设置请求标头以接受application/vnd.ms-excel,我也尝试使用application/octet-stream代替vnd.ms-excel。在任何一种情况下,我都会收到一条带有406错误消息的HTML响应。这是我的Ajax测试调用的样子:

Ext.Ajax.request({
    url: 'myservice/gettemplate',
    //dataType: 'application/vnd.ms-excel',
    headers: {
        'Accept': 'application/vnd.ms-excel, text/plain, */*'
        //'Content-Type': 'application/vnd.ms-excel'
    },
    success: function (response, options) {
        alert(1);
    },
    failure: function (response, options) {
        alert(2);
    }
});

我已经注释掉了我尝试过的线条,因为它没有帮助。这可能是一个非常简单的配置更改,但我似乎无法弄清楚。

2 个答案:

答案 0 :(得分:2)

当您使用@ResponseBody注释请求映射返回类型时,Spring将尝试使用HttpMessageConverter将对象转换为响应,如reference页面上所述:

  

@ResponseBody 与@RequestBody一样,Spring将返回的对象转换为   使用HttpMessageConverter响应正文。

您可以在此处查看可用转换器列表:Message converters

看起来任何转换器都不支持您指定的application/vnd.ms-excel。也许这就是为什么你得到406。

  

406不可接受   请求的资源只能根据发送的Accept标头生成不可接受的内容   在请求中。

您的解决方案是删除@ResponseBody注释,以其他方式处理文件下载

有关如何从Spring控制器下载文件的示例,请参阅此处:

Downloading a file from Spring controllers

Returning a file from a controller in Spring

答案 1 :(得分:1)

根据ESala的回答,我做了一些尝试。最后通过将标题和内容类型设置为HttpServletResponse来实现它。这是代码,对我有用。只需一个简单的锚标记就可以在IE和Firefox中完美地工作,甚至没有ajax调用。希望它可以帮助别人。

@RequestMapping(value ="/gettemplate", method = RequestMethod.GET)
@ResponseBody
public void getExcelTemplate(HttpServletRequest request, HttpServletResponse response) throws Exception{
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("content-disposition", "attachment; filename=TestFile.xlsx");

    InputStream fis = getClass().getClassLoader().getResourceAsStream("templates/TestFile.xlsx");
    int x = fis.available();
    byte byteArray[] = new byte[x];
    logger.info(" File size :"+byteArray.length);
    fis.read(byteArray);

    response.getOutputStream().write(byteArray);
    response.flushBuffer();
    fis.close();
}