我想读写受密码保护的 Excel 文件。如何使用 Apache POI API 实现此功能。
我想读写受密码保护的 Excel 文件。如何使用 Apache POI API 实现此功能。
POI应该能够打开受保护的xls文件(使用 org.apache.poi.hssf.record.crypt )和受保护的xlsx文件(使用 org.apache.poi.poifs.crypt )。你试过了吗?
如果你正在使用HSSF(针对xls文件),你需要在打开文件之前设置密码。你可以通过调用以下方法来实现:
org.apache.poi.hssf.record.crypto.Biff8EncryptionKey.setCurrentUserPassword(password);
接下来,HSSF应该能够打开您的文件。
对于XSSF,您需要类似以下内容:
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("protect.xlsx"));
EncryptionInfo info = new EncryptionInfo(fs);
Decryptor d = new Decryptor(info);
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
XSSFWorkbook wb = new XSSFWorkbook(d.getDataStream(fs));
或者,在较新版本的Apache POI中,WorkbookFactory支持在打开时提供密码,所以您可以采取类似以下方式的操作:
Workbook wb = WorkbookFactory.create(new File("protected.xls"), "password");
这将适用于HSSF和XSSF,根据格式选择正确的工具,并以适当的方式传递给定的密码。
// XOR/RC4 decryption for xls
Biff8EncryptionKey.setCurrentUserPassword("pass");
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File("file.xls"), true);
HSSFWorkbook hwb = new HSSFWorkbook(fs.getRoot(), true);
Biff8EncryptionKey.setCurrentUserPassword(null);
对于基于XML的格式(xlsx):
EncryptionInfo info = new EncryptionInfo(filesystem);
Decryptor d = Decryptor.getInstance(info);
try {
if (!d.verifyPassword(password)) {
throw new RuntimeException("Unable to process: document is encrypted");
}
InputStream dataStream = d.getDataStream(filesystem);
// parse dataStream
} catch (GeneralSecurityException ex) {
throw new RuntimeException("Unable to process encrypted document", ex);
}
代码:
FileInputStream fileInput = new FileInputStream("2.xls");
BufferedInputStream bufferInput = new BufferedInputStream(fileInput);
POIFSFileSystem poiFileSystem = new POIFSFileSystem(bufferInput);
Biff8EncryptionKey.setCurrentUserPassword("test");
HSSFWorkbook workbook = new HSSFWorkbook(poiFileSystem, true);
使用的jar包:
Apache POI是用于Excel处理的好API。 但是POI API仅提供读取受密码保护的Excel文件的选项。 没有写入带密码的Excel文件的选项。
查看此线程以了解有关受密码保护的Excel的更多信息。
对于 xlsx 文件,我尝试了各种解决方案都不起作用。经过多次尝试和错误,我找到了一个可行的方法。
以下是我的工作解决方案,使用 poi-4.0.1.jar 和 poi-ooxml-4.0.1.jar。
private OutputStream getEncryptingOutputStream(POIFSFileSystem fileSystem, String password) throws IOException, GeneralSecurityException
{
EncryptionInfo encryptionInfo = new EncryptionInfo(EncryptionMode.standard);
Encryptor encryptor = encryptionInfo.getEncryptor();
encryptor.confirmPassword(password);
return encryptor.getDataStream(fileSystem);
}
private void encryptSpreadSheet(String sourcePath, String destinationPath) throws IOException, GeneralSecurityException, InvalidFormatException
{
try (POIFSFileSystem fileSystem = new POIFSFileSystem())
{
//sourcePath = "/var/tmp/dummy.xlsx"
//destinationPath = "/var/tmp/dummy_encrypted.xlsx"
try (Workbook wb = WorkbookFactory.create(new File(sourcePath));
OutputStream out = getEncryptingOutputStream(fileSystem, "password");)
{
wb.write(out);
}
try (FileOutputStream fileOutputStream = new FileOutputStream(new File(destinationPath)))
{
fileSystem.writeFilesystem(fileOutputStream);
}
}
}
FileOutputStream outputStream = null;
XSSFWorkbook workbook = new XSSFWorkbook();
try {
outputStream = new FileOutputStream("Test.xlsx");
XSSFSheet shtSummary = workbook.createSheet("Test");
workbook.write(outputStream);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
outputStream.close();
}
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("mypassword");
OPCPackage opc = OPCPackage.open(new File("Test.xlsx"), PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.save(os);
opc.close();
FileOutputStream fos = new FileOutputStream("Test.xlsx");
fs.writeFilesystem(fos);
fos.close();
这段代码运行良好。此解决方案适用于 .xslx 格式。
以下代码适用于 .xls 格式。
String fname = "Test.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("mypassword");
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);
}
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());
}
}
这两个解决方案都对我有用。这是我发现可行的好方法。
try
{
InputStream is = new FileInputStream("myfile.xlsx");
POIFSFileSystem pfs = new POIFSFileSystem(is);
EncryptionInfo info = new EncryptionInfo(pfs);
Decryptor d = Decryptor.getInstance(info);
if (!d.verifyPassword("passwordForFile"))
{
System.out.println("Incorrect password!");
}
else
{
System.out.println("Correct password!");
//InputStream dataStream = d.getDataStream(pfs);
// parse dataStream
}
}
catch (Exception ex)
{
throw new RuntimeException("Unable to process encrypted document", ex);
}
org.apache.poi.EncryptedDocumentException: Export Restrictions in place - please install JCE Unlimited Strength Jurisdiction Policy files
。 - KKK