You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hilla中创建动态生成文件的下载按钮?

在Hilla中实现动态文件下载按钮

Hilla前端基于React(默认)/Vue生态,没有Vaadin Web Components中的<Anchor>组件,但可以通过两种实用方式实现动态文件下载功能:

方法一:Spring Boot控制器+前端按钮触发

这是你已验证过有响应的方案,直接通过后端接口返回文件流,前端处理下载逻辑:

后端(Spring Boot)

创建控制器方法,返回带文件流的响应:

@RestController
@RequestMapping("/api/download")
public class DownloadController {

    @GetMapping("/dynamic-file")
    public ResponseEntity<Resource> downloadDynamicFile() {
        // 动态生成文件内容(示例为CSV格式)
        String content = "姓名,年龄\n张三,25\n李四,30";
        ByteArrayResource resource = new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8));

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"dynamic-data.csv\"")
                .contentType(MediaType.parseMediaType("text/csv"))
                .body(resource);
    }
}

前端(Hilla React视图)

用普通按钮触发请求,将响应转为Blob后触发浏览器下载:

import { Button } from '@hilla/react-components/Button';

export default function DownloadView() {
    const handleDownload = async () => {
        const response = await fetch('/api/download/dynamic-file');
        if (!response.ok) throw new Error('下载失败');
        
        const blob = await response.blob();
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        // 从响应头解析文件名,或直接指定
        const disposition = response.headers.get('Content-Disposition');
        const filename = disposition?.match(/filename="?([^"]+)"?/)?.[1] || 'dynamic-file.csv';
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    };

    return (
        <div>
            <Button onClick={handleDownload}>下载动态生成文件</Button>
        </div>
    );
}

方法二:Hilla类型安全服务端调用

如果想通过Hilla的类型安全服务调用(而非直接REST接口)实现,可在服务类返回StreamResource,前端处理Blob:

后端(Hilla服务类)

@AnonymousAllowed
@Service
public class DownloadService {

    public StreamResource generateDynamicFile() {
        String content = "动态生成的文件内容示例";
        return new StreamResource("dynamic-file.txt", () -> 
                new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
    }
}

前端(Hilla React视图)

调用服务端方法,获取资源信息后完成下载:

import { Button } from '@hilla/react-components/Button';
import { downloadService } from 'Frontend/generated/endpoints';

export default function DownloadView() {
    const handleDownload = async () => {
        const resource = await downloadService.generateDynamicFile();
        const response = await fetch(resource.url);
        const blob = await response.blob();
        
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = resource.name;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    };

    return (
        <div>
            <Button onClick={handleDownload}>下载动态文件(服务端调用)</Button>
        </div>
    );
}

注:第二种方法中,StreamResource会生成临时URL,Hilla自动处理权限控制,适合需要鉴权的场景。

内容的提问来源于stack exchange,提问作者David Marko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 13:12:13