我有这个应用程序,我在JSP中开发,我希望从数据库中导出一些数据在XLS(MS Excel格式)。在tomcat下,是否可以像普通的Java应用程序一样编写一个文件,然后生成一个指向该文件的链接?或者,是否需要使用特定的API?执行此操作时是否会出现权限问题?
polkgigr1#
虽然您可以使用JExcelAPI等成熟的库,但如果您将响应MIME类型设置为“application/vnd.ms-excel”之类的内容,Excel也将读取CSV和纯HTML表。根据电子表格需要的复杂程度,CSV或HTML可以在没有第三方库的情况下为您完成这项工作。
9vw9lbht2#
不要使用内容类型为application/vnd.ms-excel的纯HTML表格。这样做基本上是在用错误的内容类型欺骗Excel,这会导致最新版本的Excel出现错误和/或警告。在Excel中编辑和保存时,它还会破坏原始HTML源文件。请不要这样做。CSV是一种标准格式,Excel默认支持它,而且它很容易生成,内存效率也很高。虽然有库,但你也可以用不到20行的代码轻松地编写一个CSV(对于那些无法抗拒的人来说很有趣)。你只需要遵守RFC 4180规范,它基本上只包含3条规则:1.字段以逗号分隔。1.如果逗号出现在字段中,则必须用双引号将字段括起来。1.如果双引号出现在字段中,则字段必须用双引号括起来,并且字段中的双引号必须用另一个双引号转义。下面是一个启动示例:
application/vnd.ms-excel
public static <T> void writeCsv (List<List<T>> csv, char separator, OutputStream output) throws IOException { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, "UTF-8")); for (List<T> row : csv) { for (Iterator<T> iter = row.iterator(); iter.hasNext();) { String field = String.valueOf(iter.next()).replace("\"", "\"\""); if (field.indexOf(separator) > -1 || field.indexOf('"') > -1) { field = '"' + field + '"'; } writer.append(field); if (iter.hasNext()) { writer.append(separator); } } writer.newLine(); } writer.flush(); }
下面是一个如何使用它的示例:
public static void main(String[] args) throws IOException { List<List<String>> csv = new ArrayList<List<String>>(); csv.add(Arrays.asList("field1", "field2", "field3")); csv.add(Arrays.asList("field1,", "field2", "fie\"ld3")); csv.add(Arrays.asList("\"field1\"", ",field2,", ",\",\",\"")); writeCsv(csv, ',', System.out); }
在Servlet中(是的,Servlet,不要使用JSP!),您基本上可以执行以下操作:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String filename = request.getPathInfo().substring(1); List<List<Object>> csv = someDAO().findCsvContentFor(filename); response.setHeader("content-type", "text/csv"); response.setHeader("content-disposition", "attachment;filename=\"" + filename + "\""); writeCsv(csv, ';', response.getOutputStream()); }
将这个servletMap到类似/csv/*的对象上,然后调用类似http://example.com/context/csv/filename.csv的对象,就这样。请注意,我添加了单独指定分隔符字符的可能性,因为Excel是否接受逗号,或分号;作为CSV字段分隔符可能取决于所使用的区域设置。请注意,我还将文件名添加到了URL pathinfo中,因为雷德蒙团队开发的某个Web浏览器无法使用正确的文件名保存下载。
/csv/*
http://example.com/context/csv/filename.csv
,
;
yuvru6vn3#
你可能需要一个库来操作Excel文件,比如JExcelAPI(“jxl”)或POI。我更熟悉jxl,它当然可以写文件。你可以生成它们,并通过提供URL来存储它们,但我不会。生成的文件是一个痛苦。它们增加了并发性、清理过程等形式的复杂性。如果您可以动态生成文件并通过标准servlet机制将其流式传输到客户机。如果生成了很多次,或者生成的代价很高,那么你可以缓存结果,但是我更倾向于把它保存在内存中,而不是作为一个文件。如果可以的话,我当然会避免通过URL直接链接到生成的文件。如果你通过servlet,它将允许你以后改变你的实现。这和OO设计中的封装概念是一样的。
xkftehaa4#
POI或JExcel都是很好的API。我个人喜欢更好的POI,加上POI是不断更新的。此外,在线有更多的关于POI的资源比JExcel,以防你有任何问题。然而,这两个做得很好。
hgb9j2n65#
也许你应该考虑使用一些报告工具,并选择将文件导出为XLS格式。我的建议是JasperReports
oogrdqng6#
try { String absoluteDiskPath = test.xls"; File f = new File(absoluteDiskPath); response.setContentType("application/xlsx"); response.setHeader("Content-Disposition", "attachment; filename=" + absoluteDiskPath); String name = f.getName().substring(f.getName().lastIndexOf("/") + 1, f.getName().length()); InputStream in = new FileInputStream(f); out.clear(); //clear outputStream prevent illegalStateException write binary data to outputStream ServletOutputStream outs = response.getOutputStream(); int bit = 256; int i = 0; try { while ((bit) >= 0) { bit = in.read(); outs.write(bit); } outs.flush(); outs.close(); in.close(); } catch (IOException ioe) { ioe.printStackTrace(); } finally { try { if(outs != null) outs.close(); if(in != null) in.close(); }catch (Exception ioe2) { ioe2.printStackTrace(); } } } catch (Exception ex) { ex.printStackTrace(); }
vsmadaxz7#
我试过像下面的JSP,它是工作正常.
<% String filename = "xyz.xls"; response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\""); java.io.File excelFile=new java.io.File("C:\\Users\\hello\\Desktop\\xyz.xls"); java.io.FileInputStream fileInputStream=new java.io.FileInputStream(excelFile); byte[] bytes = new byte[(int) excelFile.length()]; int offset = 0; while (offset < bytes.length) { int result = fileInputStream.read(bytes, offset, bytes.length - offset); if (result == -1) { break; } offset += result; } javax.servlet.ServletOutputStream outs = response.getOutputStream(); outs.write(bytes); outs.flush(); outs.close(); fileInputStream.close(); %>
7条答案
按热度按时间polkgigr1#
虽然您可以使用JExcelAPI等成熟的库,但如果您将响应MIME类型设置为“application/vnd.ms-excel”之类的内容,Excel也将读取CSV和纯HTML表。
根据电子表格需要的复杂程度,CSV或HTML可以在没有第三方库的情况下为您完成这项工作。
9vw9lbht2#
不要使用内容类型为
application/vnd.ms-excel
的纯HTML表格。这样做基本上是在用错误的内容类型欺骗Excel,这会导致最新版本的Excel出现错误和/或警告。在Excel中编辑和保存时,它还会破坏原始HTML源文件。请不要这样做。CSV是一种标准格式,Excel默认支持它,而且它很容易生成,内存效率也很高。虽然有库,但你也可以用不到20行的代码轻松地编写一个CSV(对于那些无法抗拒的人来说很有趣)。你只需要遵守RFC 4180规范,它基本上只包含3条规则:
1.字段以逗号分隔。
1.如果逗号出现在字段中,则必须用双引号将字段括起来。
1.如果双引号出现在字段中,则字段必须用双引号括起来,并且字段中的双引号必须用另一个双引号转义。
下面是一个启动示例:
下面是一个如何使用它的示例:
在Servlet中(是的,Servlet,不要使用JSP!),您基本上可以执行以下操作:
将这个servletMap到类似
/csv/*
的对象上,然后调用类似http://example.com/context/csv/filename.csv
的对象,就这样。请注意,我添加了单独指定分隔符字符的可能性,因为Excel是否接受逗号
,
或分号;
作为CSV字段分隔符可能取决于所使用的区域设置。请注意,我还将文件名添加到了URL pathinfo中,因为雷德蒙团队开发的某个Web浏览器无法使用正确的文件名保存下载。yuvru6vn3#
你可能需要一个库来操作Excel文件,比如JExcelAPI(“jxl”)或POI。我更熟悉jxl,它当然可以写文件。你可以生成它们,并通过提供URL来存储它们,但我不会。生成的文件是一个痛苦。它们增加了并发性、清理过程等形式的复杂性。
如果您可以动态生成文件并通过标准servlet机制将其流式传输到客户机。
如果生成了很多次,或者生成的代价很高,那么你可以缓存结果,但是我更倾向于把它保存在内存中,而不是作为一个文件。如果可以的话,我当然会避免通过URL直接链接到生成的文件。如果你通过servlet,它将允许你以后改变你的实现。这和OO设计中的封装概念是一样的。
xkftehaa4#
POI或JExcel都是很好的API。我个人喜欢更好的POI,加上POI是不断更新的。此外,在线有更多的关于POI的资源比JExcel,以防你有任何问题。然而,这两个做得很好。
hgb9j2n65#
也许你应该考虑使用一些报告工具,并选择将文件导出为XLS格式。我的建议是JasperReports
oogrdqng6#
vsmadaxz7#
我试过像下面的JSP,它是工作正常.