Редактировать: разрешено. Я обошел ibatis/ApachePOI, написав jdbc-коннектор в базе данных, получив blob и сбросив его в файл. Когда-нибудь, я хотел бы точно знать, почему это пришло в голову - но сегодня я счастлив, что это позади.Oracle Blob to XLS рабочий лист
Резюме: Я получаю Oracle blobs и используя Apache POI для восстановления двоичных файлов Excel для прохождения через SOAP-сервисный уровень. Клиент .Net записывает их в .xls-файлы просто отлично, но имеет поврежденные файлы при записи в каталог UNIX.
Деталь: У меня есть Excel blobs, хранящиеся в таблице оракулов. Эти капли записываются с использованием iBatis и вытаскиваются с использованием этой (усеченной) карты результатов.
<resultMap id="report" class="Report">
<result column="content" property ="content" typeHandler="BlobByteArrayTypeHandler"/>
Отчеты excel создаются с использованием Apache.POI нашими службами Java. На данный момент наш клиент (.net) запрашивает службу для байтового массива, который записывается на компьютер без ошибок - просто сбрасывает байты в файл.
Эти отличные файлы в порядке.
Проблема, с которой я столкнулась, состоит в том, что у нас есть новое требование, чтобы мы записывали эти файлы в файловую систему UNIX для дальнейшей обработки.
Все попытки этого потерпели неудачу. Вот некоторые примеры кода:
private void writeReportDumpBytes(Report report) {
File file = new File("report.xls");
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(report.getContent());
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeReportWithEncoding(Report report, String encoding) {
File file = new File("Report.xls");
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, encoding);
Writer out = new BufferedWriter(outputStreamWriter);
String reportBytes = new String(report.getContent());
out.write(reportBytes.toCharArray());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeReportHssfPoifileSystem(Report report) {
try {
InputStream byteStream = new ByteArrayInputStream(report.getContent());
POIFSFileSystem fs = new POIFSFileSystem(byteStream);
HSSFWorkbook workbook = new HSSFWorkbook(fs);
FileOutputStream fileOut = new FileOutputStream("Report.xls");
workbook.write(fileOut);
fileOut.flush();
fileOut.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
private void writeReportApacheIO(Report report) {
File file = new File("Report.xls");
try {
logReportBytes(report, "Apache IO");
FileUtils.writeByteArrayToFile(file, report.getContent());
} catch (IOException e) {
log.error("Caught IOException", e);
}
}
Для того, чтобы диагностировать это, я попытался схватить каплю из Oracle, и сохранить его в файл. В исполняемом файле «bare-bones jar» я смог прочитать байты из этого файла и переписать его, используя вышеуказанные методы в нашем окне UNIX, - и все они работают.
Однако из нашего кода файлы excel повреждены или отсутствуют сведения заголовков из Apache.POI. Открытие поврежденных/плохих двоичных файлов в текстовом редакторе показывает повторяющийся шаблон из 64 байтов. Это не допустимый двоичный файл xls.
Что-то идет вбок. Blob является действительным двоичным кодом xls, и мы просто получаем байты (используя iBatis выше) и передаем их обратно через объект HSSFWorkbook и пытаемся написать с использованием методов, как я их показал.
/**
* Return the byte array based on the workbook.
*
* @return
* @throws IOException
*/
public byte[] getContent() throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
this.workBook.write(bos);
return bos.toByteArray();
}
Специфическая ошибка я получаю при использовании Apache POI является:
java.io.IOException: block[ 0 ] already removed
at org.apache.poi.poifs.storage.BlockListImpl.remove(BlockListImpl.java:97)
at org.apache.poi.poifs.storage.BlockAllocationTableReader.fetchBlocks(BlockAllocationTableReader.java:190)
at org.apache.poi.poifs.storage.BlockListImpl.fetchBlocks(BlockListImpl.java:130)
at org.apache.poi.poifs.property.PropertyTable.<init>(PropertyTable.java:79)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:171)
Файлы Excel - это двоичные данные. Вы, кажется, используете Writers и Encodings, которые должны использоваться только с обычным текстом. Использование их с двоичными данными ломает вещи! Что произойдет, если вы заархивируете всех писателей и просто работаете с байтами/потоками? – Gagravarr
Мой первый пример использует FileOutputStream только для записи, очень похожую на рабочий код .Net, но не работает в Unix. – hoosierChessGeek