【问题标题】:Writing spreadsheet to a blob column and retrieving it back using POI将电子表格写入 blob 列并使用 POI 将其取回
【发布时间】:2017-02-17 16:58:50
【问题描述】:

我们需要将上传的电子表格存储在 Oracle 数据库 blob 列中。 用户将使用 ADF UI 上传电子表格,并且相同的电子表格将保存到数据库并稍后检索。 我们正在使用 POI 来处理电子表格。 上传的文件被转换为 byte[] 并发送到 appserver。 Appserver 将相同的内容保存到 blob 列。 但是当我稍后尝试检索相同内容时,我看到“Excel 在 *****.xlsx 中发现不可读的内容。你想恢复此工作簿的内容吗?”信息。 我可以通过 将 byte[] 转换为 XSSFWorkbook 并将其转换回 byte[] 并将其持久化。 但根据我的要求,我可能会得到非常大的电子表格,初始化 XSSFWorkbook 可能会导致内存不足问题。 从上传的电子表格中获取字节[]的代码如下

 if (uploadedFile != null) {
        InputStream inputStream;
        ByteArrayOutputStream byteArrayOutputStream = new         ByteArrayOutputStream();
                inputStream = uploadedFile.getInputStream();
                int c = 0;
                while (c != -1) {
                    c = inputStream.read();
                    byteArrayOutputStream.write((char) c);
                }
                bytes = byteArrayOutputStream.toByteArray();

            }

并且相同的 byte[] 被持久化到一个 blob 列中,如下所示。 1. 将此 byte[] 分配给 BlobCloumn 2. 用 bolobColumn 更新 SQL Update 语句 3. 执行语句。

完成上述步骤后,按如下方式检索电子表格。 1. 阅读 BlobColumn 2. 从 BlobColumn 中获取 bytes[] 3. 设置响应的内容类型以支持电子表格。 4. 发送字节[]。

但是当我打开上面下载的电子表格时,我收到了电子表格损坏的错误。

如果我在从 UI 接收到 byte[] 后引入如下附加步骤,问题就解决了。

InputStream is = new ByteArrayInputStream(uploadedSpreadSheetBytes);
     XSSFWorkbook uploadedWorkbook = new XSSFWorkbook(is);

然后,再次从 XSSFWorkbook 导出 byte[],如下所示

byteArrayOutputStream = new ByteArrayOutputStream();
        workbook.write(byteArrayOutputStream);
        byte[] spreadSheetBytes = byteArrayOutputStream.toByteArray();

我觉得将 byte[] 转换为 XSSFWorkbook,然后将 XSSFWorkbook 转换回 byte[] 是多余的。

任何帮助将不胜感激。 谢谢。

【问题讨论】:

  • 某处引入了损坏,但不清楚您的进程是什么。你能一步一步把它拼出来,然后告诉我们错误发生在哪里吗?包括有关如何保存电子表格以及通过哪个过程保存的细节。转换也是如此:你是如何做到的,以及正在做的过程。我最初的想法是 POI 写入 OutputStream,也许 ByteArrayOutputStream 可以与 toString() 一起使用。

标签: java apache-poi blob


【解决方案1】:

可以通过使用基于事件的解析 (SAX) 而不是初始化整个 XSSFWorkbook 来避免内存问题。这样,您只处理消耗较少内存的文件部分。有关 SAX 解析的更多信息,请参阅 the POI spreadsheet how-to page。 您也可以增加 JVM 内存,但这当然不能保证。

【讨论】:

  • 我们尝试用它来阅读电子表格。但是这里的情况只是将 byte[] 写入数据库。如果我们写入来自 UI 的 byte[],我们会在打开电子表格时看到损坏的电子表格消息。相反,如果我们将 byte[] 转换为 XSSFWorkbook 并取回 bytes[] 并将它们写入 DB,则不会观察到任何问题。
  • 如何将 byte[] 转换为 XSSFWorkbook?可能是字符编码、文件头等出了问题。我猜测转换为 XSFFWorkbook 的过程会添加一些必要的字节。比较初始 byte[] 的大小和从 XSSFWorkbook 取回 byte[] 后的大小。
  • @Vasantha:"但这里的情况只是将 byte[] 写入数据库。"是的,但是我们怎么知道你是怎么做到的呢?这样做不仅有一种可能性,而且您还没有提供任何代码。请通过编辑此问题在您的问题中显示将字节 [] 写入数据库的代码。
  • 当我仔细观察这一点时,我发现我从下面的块中取出的字节[]与上传的电子表格的大小不同。
  • if (uploadedFile != null) { InputStream inputStream; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); inputStream = uploadFile.getInputStream();诠释 c = 0; while (c != -1) { c = inputStream.read(); byteArrayOutputStream.write((char) c); } 字节 = byteArrayOutputStream.toByteArray(); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多