使用Apache POI创建受密码保护的Excel文件?

时间:2012-01-11 09:56:30

标签: java excel apache-poi xls

我正在开发一个简单的Java程序来使用(Apache POI)API创建Excel文件。 我使用Oracle 10g作为数据库并使用ojdbc14 JAR文件。

我有一个名为USERINFO的表,有三列,即USERNAMEPASSWORDNAME. 现在使用Apache POI,我已经能够将所有行放在Excel文件中。

由于该文件包含敏感数据,如用户名和密码,我想让它受密码保护。 在论坛上,我发现了如何读取受密码保护的文件,而不是如何创建它们。 那我怎么能做到这一点?

4 个答案:

答案 0 :(得分:15)

已更新:自版本3.10起,POI支持XLSX文件的加密和解密。见the "Encryption Support" page on POI's website。以下内容仍与XLS二进制工作簿相关。

  

根据the "Encryption Support" page on POI's website POI支持读取加密的XLS和XLSX文件。该页面上未提及加密,这意味着它不受支持。这由searching the POI site for "encrypt"支持,它只返回少数几个与解密有关的结果。我还看了一下他们的加密实现的来源,它似乎只处理解密。这并不奇怪; POI专为数据提取和搜索索引而设计,而不是用于创建新的电子表格。

     

正如其他人所建议的那样,通常可以通过在Excel中创建模板然后使用POI用数据填充它来解决POI中缺少的功能。不幸的是,这对加密不起作用,因为加密电子表格的文件格式完全不同。

如果您愿意为商业软件付费,最新版本的ExtenXLS会对Excel支持的所有加密格式提供完全读写支持。只需构建一个EncryptedWorkBookHandle而不是正常WorkBookHandle。这将使用未经修改的JRE支持的最强密码,用于XLS的RC4和用于XLSX的128位AES。如果您想使用256位AES和OOXML,并且已经安装了JCE unlimited policy,则可以使用MSOfficeEncrypter类进行安装。

JExcelAPI是一种流行的开源Java电子表格API,似乎根本不支持加密。 Aspose.Cells,商业广告supports stong encryption。 Actuate e.Spreadsheet的文档似乎从'net中消失了,所以我不知道它是否支持加密。

由于所有免费提供的Java电子表格API似乎都不支持编写加密电子表格,如果您不愿意使用商业软件,则需要提出解决方法。例如,您可以将电子表格写入加密的ZIP文件中。 java.util.zip不支持加密,但它看起来像Zip4j

完全披露:我在ExtenXLS背后的公司Extentech工作。

答案 1 :(得分:8)

创建受密码保护的Excel文件或使用现有模板并使其受密码保护。这将为用户提供“只读”访问权限。这是一个例子,我有一个密码为“秘密”的Excel文件:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;

public class ProtectedExcelFile {

    public static void main(final String... args) throws Exception {

        String fname = "C:\\Documents and Settings\\sadutta\\Desktop\\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);
        }
        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());
            }
        }
    }
}

您应该能够编写或修改现有模板。完成后,覆盖模板。如果您的模板应该多次使用,您可能希望将模板复制到其他位置,然后使用代码进行修改。

答案 2 :(得分:4)

我经常发现POI要做更复杂的事情,一个有用的方法是在Excel中使用高级功能(例如宏)创建电子表格,然后使用POI读取电子表格,填充并写出来。 POI通常会维护电子表格功能并添加数据。

我没有试过这个密码,但我怀疑它值得一个实验。

有关详细信息,请参阅busy developer's guide

答案 3 :(得分:0)

以下程序将在给定的excel路径中生成受密码保护的excel文件

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class MyTest1 {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\Raju\\Desktop\\workbook1.xlsx");
        try {
            file.createNewFile();
            OutputStream fileOut = new FileOutputStream(file);
            XSSFWorkbook wb = new XSSFWorkbook();
            Sheet sheet = wb.createSheet();
            Row row = sheet.createRow(0);
            Cell cell = row.createCell(0);
            cell.setCellValue("Venu");
            wb.write(fileOut);
            wb.close();
            fileOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (POIFSFileSystem fs = new POIFSFileSystem()) {
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
            // EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile,
            // CipherAlgorithm.aes192, HashAlgorithm.sha384, -1, -1, null);
            Encryptor enc = info.getEncryptor();
            enc.confirmPassword("hello");
            // Read in an existing OOXML file and write to encrypted output stream
            // don't forget to close the output stream otherwise the padding bytes aren't
            // added
            try (OPCPackage opc = OPCPackage.open(file, PackageAccess.READ_WRITE);
                    OutputStream os = enc.getDataStream(fs)) {
                opc.save(os);
            } catch (InvalidFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (GeneralSecurityException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // Write out the encrypted version
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fs.writeFilesystem(fos);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (IOException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        System.out.println("Excel file exported");
    }
}

使用maven依赖

<dependency>
 <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>

是的,我知道我们可以优化这么多代码。在高层次上,程序正在运行