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

Posted

技术标签:

【中文标题】使用 Spring Boot 和 Thymeleaf 创建文件下载链接【英文标题】:Creating a file download link using Spring Boot and Thymeleaf 【发布时间】:2015-07-01 04:57:05 【问题描述】:

这听起来像是一个微不足道的问题,但经过数小时的搜索,我还没有找到答案。据我了解,问题是我试图从控制器返回一个FileSystemResource,Thymeleaf 希望我提供一个String 资源,它将使用它来呈现下一页。但由于我返回的是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

我使用的控制器映射是:

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

我的 html 链接如下所示:

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

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

【问题讨论】:

&lt;a th:href="$'products/download?id=' + product.id"&gt;&lt;span th:text="$product.name"&gt;&lt;/span&gt;&lt;/a&gt;开头的$应该是@,你可以试试吗? 如果我使用 @product.id 不会被实际产品 ID 替换。 因为它应该是th:href="@'products/download?id=' + $product.id",如documentation中所述 是的。但错误仍然存​​在。实际 id 现在显示在 get 请求中。 @PatrickLC 成功了!如果你把它作为答案,我会接受它。 【参考方案1】:

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

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

然后您还需要更改控制器并包含@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()));

【讨论】:

嘿。刚才我注意到你有| 符号而不是通常的'。有什么我应该知道的吗? 这只是连接的另一种方式,但比使用 '.检查这个答案:***.com/a/22064656/4316870 太棒了!谢谢(你的)信息! :)【参考方案2】:

有一个像

这样的 href url
<a th:href="@|/download?id=$obj.id|">download</a>

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

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

        
    

【讨论】:

这对我有用,第一个答案让我的屏幕上满是奇怪的字符......【参考方案3】:

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

手册摘录

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

【讨论】:

【参考方案4】:

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

这解决了:

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

【讨论】:

【参考方案5】:

Thymeleaf &lt;td&gt;&lt;a th:href="$fileDetail.MsgFileName" th:text="$fileDetail.MsgFileName" /&gt;&lt;/td&gt;.URL 在服务器端准备,href 在客户端创建

【讨论】:

以上是关于使用 Spring Boot 和 Thymeleaf 创建文件下载链接的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot:在Spring Boot中使用Mysql和JPA

使用 spring boot 和 spring-boot-maven-plugin 生成战争时排除 application.properties

Spring —— Spring Boot 创建和使用

Spring Boot(十六):使用Jenkins部署Spring Boot

处理spring-boot-starter-quartz和spring-boot-starter-websocket同时使用报错

spring boot(十六)使用Jenkins部署spring boot