英文:
Download CSV via PostgreSQL in Vaadin
问题
我有一个Vaadin 14应用程序,从PostgreSQL 11数据库检索数据。
使用Java 8和9.4-1202-jdbc42。
我尝试为数据库中的表格实现下载功能。我创建了一个带有以下代码段的按钮。它有效,并且我可以下载示例数据。
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()方法的好信息。
英文:
I got a Vaadin 14 application, which retrieves data from a PostgreSQL 11 database.
Using Java 8 with 9.4-1202-jdbc42.
I try to achieve a download feature for a table of the database. I created a button with following code snippet. It is working and I can download the example data.
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);
But I want to download data from the PostgreSQL database, not some static input. So I do a "COPY ... TO STDOUT"-request using the CopyManager (org.postgresql.copy.CopyManager).
String sql = "SELECT * FROM table";
copyManager.copyOut("COPY (" + sql + ") TO STDOUT WITH (FORMAT CSV, HEADER)", outputStream);
Edit:
Creating the StreamResource works now, but PostgreSQL doesn't like my sql statement.
Currently this creates an empty csv only with the table headers.
CopyOut copiedData = copyManager.copyOut(sqlRequest);
ByteArrayInputStream stream = new ByteArrayInputStream(copiedData.readFromCopy());
return new StreamResource("foo.csv", () -> stream);
PostgreSQL response for the same sql request in PgAdmin:
COPY (SELECT * FROM table) TO STDOUT WITH (FORMAT CSV, HEADER)
ERROR: can't execute COPY TO: use the copy_to() method instead
If I replace STDOUT with a filename, it works in PgAdmin
COPY (SELECT * FROM table) TO 'D:\test.csv' WITH (FORMAT CSV, HEADER);
COPY 63
Query returned successfully in 881 msec.
Although I understand that using STDOUT doesn't make much sense in the PgAdmin console, it should work via JDBC, right?
What's wrong with my sql statement? I can't find any good information about copy_to() method.
答案1
得分: 2
不必直接从数据库查询中创建CSV文件,您可以使用OpenCSV库将CSV文件创建为您的ResultSet。但是,您实际上并不需要文件系统中的物理文件。甚至存在一些潜在的严重缺点-文件占用有限的磁盘空间,I/O操作昂贵,并且存在将一个用户的文件意外链接到不同用户的风险。StreamResource
接受任何类型的输入流,因此在内存中执行整个操作可能是一个更好的主意,而无需中间的物理文件。
英文:
Instead of creating a CSV file directly out of your database query, you could use the OpenCSV library to create a CSV file out of your ResultSet.
However, you don't really need the physical file in your file system. There are even some potentially serious downsides to this - files eat up limited disk space, I/O is expensive and there's a potential for accidentally linking one user's file to a different user. StreamResource
accepts any kind of input stream, so it might be a better idea to keep the whole operation in memory, without an intermediate physical file.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论