When I try to create a workbook from an already existing xls received as an InputStream using apache poi 4.1.2:
InputStream inputStream = new ByteArrayInputStream(input);
Workbook workbook = null;
try {
workbook = WorkbookFactory.create(inputStream);
} catch (IOException e) {
...
}
I received the following exception: "Caused by: java.lang.IndexOutOfBoundsException: Unable to read 512 bytes from 328192 in stream of length 328192"
If I open the xls file and just save it before uploaded it again, it works fine.
Related
I use an endpoint in order to upload a .xlsx or .xls file. After that I am storing the encoded excel file (base64) to a String. In order to parse and handle the values of excel I need to decode that file.
Upload service class:
public BulkUploadResponse validateFile(BulkUploadRequest request) {
final String pfx = String.format("validateFile: ");
BulkUploadResponse response = new BulkUploadResponse();
String delimiters = "\\s+|,";
String[] tokensVal = request.getContent().split(delimiters);
String fileContentEncoded = tokensVal[tokensVal.length-1];
InputStream fileContent = new ByteArrayInputStream(new String(Base64.getDecoder().decode(fileContentEncoded), UTF_8).getBytes(UTF_8));
Then I call a class where I convert the data included in excel file parsing as a parameter the fileContent which is supposed to be decoded.
BulkVignetteCustomer customerVignettes = bulkVignetteCustomerConverter.convert(fileContent);
Finally I use the Workbook package in order to parse that file
Example:
#Override
public BulkVignetteCustomer convert(InputStream fileContent) {
try {
Workbook wb = WorkbookFactory.create(fileContent);
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
Sheet sheet = wb.getSheetAt(0);
Iterator rows = sheet.iterator();
(...)
Error that I get:
java.lang.IllegalArgumentException: Your InputStream was neither an OLE2 stream, nor an OOXML stream at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:89)
Any thoughts on how to decode the file without any errors?
Thank you!
This line seems very strange to me:
InputStream fileContent = new ByteArrayInputStream(new String(Base64.getDecoder().decode(fileContentEncoded), UTF_8).getBytes(UTF_8));
You have an Excel file which isn't plain text but a big binary blob at this stage. Why do you use a String here?
So the binary blob is encoded as Base64. You can directly get the bytes out of the decoder and put them into the ByteArrayInputStream:
InputStream fileContent = new ByteArrayInputStream(Base64.getDecoder().decode(fileContentEncoded));
To verify this part of your application you can store the bytes to a file and try to open it with Excel.
I want to protect a .doc file with password using apache poi. I am getting this error while running code. please help me
Exception in thread "main"
org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: The
supplied data appears to be in the OLE2 Format. You are calling the
part of POI that deals with OOXML (Office Open XML) Documents. You
need to call a different part of POI to process this data (eg HSSF
instead of XSSF) at
org.apache.poi.openxml4j.opc.internal.ZipHelper.verifyZipHeader(ZipHelper.java:179)
at
org.apache.poi.openxml4j.opc.internal.ZipHelper.openZipFile(ZipHelper.java:237)
at
org.apache.poi.openxml4j.opc.ZipPackage.(ZipPackage.java:134)
at
org.apache.poi.openxml4j.opc.ZipPackage.(ZipPackage.java:117)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:257)
POIFSFileSystem fs=new POIFSFileSystem();
EncryptionInfo info=new EncryptionInfo(EncryptionMode.agile);
Encryptor enc=info.getEncryptor();
enc.confirmPassword("user");
OPCPackage opc=OPCPackage.open("D:/Amar.doc", PackageAccess.READ_WRITE);
OutputStream os=enc.getDataStream(fs);
opc.save(os);
opc.close();
FileOutputStream stream=new FileOutputStream("D:/ao.doc");
fs.writeFilesystem(stream);
stream.close();
System.out.println("running");
I checked and reference to Apache POI documentation, it says that the password encryption for .doc file support since version 3.17, so I give it a try.
It must use HWPFDocument instead to open your doc file.
Then you need to set password by:
Biff8EncryptionKey.setCurrentUserPassword(password);
Complete method:
public static void encryptDocFile(File inputDocFile, File outputDocFile, String password) {
try {
FileInputStream fileInput = new FileInputStream(inputDocFile);
BufferedInputStream bufferInput = new BufferedInputStream(fileInput);
POIFSFileSystem poiFileSystem = new POIFSFileSystem(bufferInput);
// Setting password
Biff8EncryptionKey.setCurrentUserPassword(password);
HWPFDocument wordDoc = new HWPFDocument(poiFileSystem);
FileOutputStream fileOut = new FileOutputStream(outputDocFile);
wordDoc.write(fileOut);
bufferInput.close();
fileOut.close();
wordDoc.close();
System.out.println("Encrypted successfully");
} catch (IOException e) {
System.out.println("Failed to encrypt doc file");
e.printStackTrace();
}
}
Or you can checkout the complete code here:
If you have further question or feedback, please let me know. Thank you
I have created a jar for sending mail using java. I have to attach an excel file with mail. Am using HSSF for creating worksheet. But I need to encrypt the attachment with password. I succeeded. But when I open the attachment directly from mail through Outlook it's not asking password. and when I copy to any folder and then if I try to open , it works properly. Can anyone, please help?
public static void main(final String... args) throws Exception {
String fname = "D:\\Mail\\Sample.xls";
FileInputStream fileInput = null;
BufferedInputStream bufferInput = null;
POIFSFileSystem poiFileSystem = null;
FileOutputStream fileOut = null;
try {
fileInput = new FileInputStream(fname);
bufferInput = new BufferedInputStream(fileInput);
poiFileSystem = new POIFSFileSystem(bufferInput);
Biff8EncryptionKey.setCurrentUserPassword("secret");
HSSFWorkbook workbook = new HSSFWorkbook(poiFileSystem, true);
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("THIS WORKS!");
fileOut = new FileOutputStream(fname);
workbook.writeProtectWorkbook(Biff8EncryptionKey.getCurrentUserPassword(), "");
workbook.write(fileOut);
File file = new File("D:\\Mail\\Sample.xls");
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum);
System.out.println("read " + readNum + " bytes,");
}
} catch (IOException ex) {
}
byte[] bytes = bos.toByteArray();
// Code for sending mail
} catch (Exception ex) {
System.out.println(ex.getMessage());
} finally {
try {
bufferInput.close();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
try {
fileOut.close();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Method HSSFWorkbook.writeProtectWorkbook(...) is only meant to protect the workbook from being written to / modified.
If you try to open it in read+write mode (default in Windows folders), it will ask you for the password.
But if you open it in read-only mode, which is what Outlook does with attachments, it will let you view the contents since you can't write over them and thus you don't need the write password.
That's the reason you can view (but not edit) it in Outlook but not when you open it from a folder.
I don't know if the latest version of Apache POI supports full password protection for an HSSFWorkBook (a quick Google search says it doesn't, but who knows).
If it doesn't, you can work around this problem by making a password-protected ZIP file with the excel in it, and attaching the ZIP file instead.
I am working in a project which is already developed. Now I have a task to generate excel file using Apache poi API.
My problem is I have PrinWriter object available instead of OutputStream.
workbook.write(outputStream);
How to tackle this situation?
File f=new File("c://newfolder//lijo.xls");
PrintWriter out=new PrintWriter(f);
FileOutputStream fout=new FileOutputStream(f);
for converting from one output stream to another just pass the reference value
example to convert file to fileoutput stream
File file=new File("c://lijo.xls");
FileOutputStream outputStream=new FileOutputStream(file);
If you work on web project you may use ServletOutputStream and doing something like this
Workbook wb = new HSSFWorkbook();
ServletOutputStream out = response.getOutputStream();
wb.write(out);
out.flush();
out.close();
Or you can use FileInputStream
Workbook wb = WorkbookFactory.create(new FileInputStream("MyExcel.xlsx"));
5i need to convert a HSSFWorkbook (Apache's POI) to an ByteArray and later to convert the ByteArray back to the HSSFWorkbook. The following TestCase illustrates my problem:
#Test
public void testXLSExportImport(){
try {
InputStream is = new FileInputStream(FILEPATH);
HSSFWorkbook wb = new HSSFWorkbook(is);
byte[] exported = wb.getBytes();
HSSFWorkbook wb2 = new HSSFWorkbook(new ByteArrayInputStream(exported));
//in the line above the exception is thrown
} catch (Exception e) {
assertTrue(false);
}
}
the testcase fails with the exception: java.io.IOException: Invalid header signature; read 0x0005060000100809, expected 0xE11AB1A1E011CFD0
(I am using Apaches POI 3.5-beta3)
I hope somebody can help me... how can I get it work?!
You're not writing the workbook correctly! You need to use the write(Outputstream) call.
As shown in the various examples on the website, your code should instead be:
InputStream is = new FileInputStream(FILEPATH);
HSSFWorkbook wb = new HSSFWorkbook(is);
ByteArrayOutputStream out = new ByteArrayOutputStream();
wb.write(out);
HSSFWorkbook wb2 = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
Also, don't open a Workbook from a FileInputStream, if you have a File use that directly. Opening from a File uses less memory than from a Stream.