java 使用 Spring Boot 和 Thymeleaf 创建文件下载链接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29816121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 15:59:11  来源:igfitidea点击:

Creating a file download link using Spring Boot and Thymeleaf

javadownloadspring-bootthymeleaf

提问by shyam

This might sound like a trivial question, but after hours of searching I am yet to find an answer to this. The problem, as far as I understand, is that I am trying to return a FileSystemResourcefrom the controller and Thymeleaf expects me to supply a Stringresource using which it will render the next page. But since I am returning a FileSystemResource, I get the following error:

这听起来像是一个微不足道的问题,但经过数小时的搜索,我还没有找到答案。据我所知,问题在于我试图FileSystemResource从控制器返回 a并且 Thymeleaf 希望我提供一个String资源,它将使用它来呈现下一页。但是由于我返回了 a FileSystemResource,因此出现以下错误:

org.thymeleaf.exceptions.TemplateInputException: Error resolving template "products/download", template might not exist or might not be accessible by any of the configured Template Resolvers

The controller mapping I have used is:

我使用的控制器映射是:

@RequestMapping(value="/products/download", method=RequestMethod.GET)
public FileSystemResource downloadFile(@Param(value="id") Long id) {
    Product product = productRepo.findOne(id);
    return new FileSystemResource(new File(product.getFileUrl()));
}

My HTML link looks something like this:

我的 HTML 链接如下所示:

<a th:href="${'products/download?id=' + product.id}"><span th:text="${product.name}"></span></a>

I don't want to be redirected anywhere, I just need the file downloaded once the link is clicked. Is this actually the right implementation? I'm not sure.

我不想被重定向到任何地方,我只需要在单击链接后下载文件。这实际上是正确的实现吗?我不确定。

回答by Leandro Carracedo

You need to change the th:hrefto look like:

您需要将其更改th:href为如下所示:

<a th:href="@{|/products/download?id=${product.id}|}"><span th:text="${product.name}"></span></a>

Then also you need to change your controller and include the @ResponseBodyannotation:

然后您还需要更改控制器并包含@ResponseBody注释:

@RequestMapping(value="/products/download", method=RequestMethod.GET)
@ResponseBody
public FileSystemResource downloadFile(@Param(value="id") Long id) {
    Product product = productRepo.findOne(id);
    return new FileSystemResource(new File(product.getFileUrl()));
}

回答by Padmanabhan Velu

Have a href url like

有一个像这样的href url

<a th:href="@{|/download?id=${obj.id}|}">download</a>

Then In controller define like below to write the file to the response object.

然后在控制器中定义如下将文件写入响应对象。

@RequestMapping(value="/download", method=RequestMethod.GET)
public void downloadFile(@Param(value="id") Long id,HttpServletResponse response) {
        try {
            Ticket ticket = this.findById(id);
        String fileName =  Paths.get(property.getFileLocation()).resolve(ticket.getFilePath()).toString();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        String headerKey = "Content-Disposition";
        String headerValue = String.format("attachment; filename=\"%s\"", fileName);
        response.setHeader(headerKey, headerValue);
        FileInputStream inputStream;
        try {
            inputStream = new FileInputStream(fileName);
            try {
                int c;
                while ((c = inputStream.read()) != -1) {
                response.getWriter().write(c);
                }
            } finally {
                if (inputStream != null)
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    response.getWriter().close();
            }
        } catch (IOException e) {
            e.printStackTrace();

        }
    }

回答by Andrei Epure

Thymeleaf is very well documented, you can find about literal substitutions(what Leandro showed above) in the manual - section 4.7

Thymeleaf 有很好的文档记录,您可以在手册中找到文字替换(Leandro 上面展示的内容) -第 4.7 节

Excerpt from the manual

摘自手册

<span th:text="|Welcome to our application, ${user.name}!|">

回答by Vetras

for me, the answer from @leandro-carracedo worked but the browser would just list the file contents, not download.

对我来说,@leandro-carracedo 的回答有效,但浏览器只会列出文件内容,而不是下载。

This fixed that:

这修复了:

<a download="results.csv" th:href=... </a>