【问题标题】:Download CSV via PostgreSQL in Vaadin在 Vaadin 中通过 PostgreSQL 下载 CSV
【发布时间】:2020-09-13 00:43:05
【问题描述】:

我有一个 Vaadin 14 应用程序,它从 PostgreSQL 11 数据库中检索数据。 将 Java 8 与 9.4-1202-jdbc42 一起使用。

我尝试实现一个数据库表的下载功能。我使用以下代码 sn-p 创建了一个按钮。它正在运行,我可以下载示例数据。

StreamResource resource = new StreamResource("foo.csv", () -> new ByteArrayInputStream("foo,foo2,foo3\nboo,boo2,boo3".getBytes()));
Button button = new Button("Click to download");
FileDownloadWrapper buttonWrapper = new FileDownloadWrapper(resource);
buttonWrapper.wrapComponent(button);
add(buttonWrapper);

但我想从 PostgreSQL 数据库下载数据,而不是一些静态输入。所以我使用 CopyManager (org.postgresql.copy.CopyManager) 执行“COPY ... TO STDOUT”请求。

String sql = "SELECT * FROM table";
copyManager.copyOut("COPY (" + sql + ") TO STDOUT WITH (FORMAT CSV, HEADER)", outputStream);

编辑: 现在可以创建 StreamResource,但是 PostgreSQL 不喜欢我的 sql 语句。 目前,这只会创建一个带有表头的空 csv。

CopyOut copiedData = copyManager.copyOut(sqlRequest);
ByteArrayInputStream stream = new ByteArrayInputStream(copiedData.readFromCopy());
return new StreamResource("foo.csv", () -> stream);

PgAdmin 中相同 sql 请求的 PostgreSQL 响应:

COPY (SELECT * FROM table) TO STDOUT WITH (FORMAT CSV, HEADER)
ERROR:  can't execute COPY TO: use the copy_to() method instead

如果我用文件名替换 STDOUT,它可以在 PgAdmin 中使用

COPY (SELECT * FROM table) TO 'D:\test.csv' WITH (FORMAT CSV, HEADER);
COPY 63
Query returned successfully in 881 msec.

虽然我知道在 PgAdmin 控制台中使用 STDOUT 没有多大意义,但它应该通过 JDBC 工作,对吧?

我的 sql 语句有什么问题?我找不到任何关于 copy_to() 方法的好信息。

【问题讨论】:

    标签: java sql postgresql vaadin


    【解决方案1】:

    您可以使用 OpenCSV library 从 ResultSet 中创建 CSV 文件,而不是直接从数据库查询中创建 CSV 文件。

    但是,您实际上并不需要文件系统中的物理文件。这甚至有一些潜在的严重缺点——文件占用了有限的磁盘空间,I/O 很昂贵,并且有可能意外地将一个用户的文件链接到另一个用户。 StreamResource 接受任何类型的输入流,因此最好将整个操作保存在内存中,而不需要中间物理文件。

    【讨论】:

    • 感谢您的解释。是的,物理文件应该只提供给用户(按下下载按钮)。我不想把它保存在服务器上。我想我必须阅读更多关于一般 I/O 主题的内容。
    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 2020-01-21
    • 2016-06-03
    • 2014-03-19
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多