2016-12-28 73 views
-1

我没有权限将文件保存到文件系统。我可以在网上找到的所有例子都是使用文件系统。我想用Apache POI创建一个密码保护的excel文件,然后把它下载到Servlet.getOutputStream()

我想在内存中创建如下工作簿:

HSSFWorkbook workbook = new HSSFWorkbook(); 

将数据写入工作簿... 使工作簿密码保护?

然后写工作簿如下输出流:

workbook.write(servlet.getOutputStream()); 
+0

您正在编写一个没有对文件系统的写入权限的Servlet吗? – EJP

+0

截至目前,我已经实现了[ChunkedCipherOutputStream](https://svn.apache.org/repos/asf/poi/trunk/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java) ,它在加密过程中使用,以使用temp。文件,以便能够加密较大的文件而不会受到内存限制。如果你想单独留在内存中,你需要在本地修补该类。 – kiwiwings

+0

...还有一些其他地方需要修补:(例如[AgileEncryptor](https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/ org/apache/poi/poifs/crypt/agile/AgileEncryptor.java)类 – kiwiwings

回答

0

我能得到以下用的HttpServlet和HSSFWorkbook .xls文件的工作 - WorkbookServlet.java:

package com.joshden; 

import java.io.IOException; 
import java.io.OutputStream; 

import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; 
import org.apache.poi.hssf.usermodel.HSSFWorkbook; 
import org.apache.poi.ss.usermodel.Workbook; 

@WebServlet("/workbook") 
public class WorkbookServlet extends HttpServlet { 
    private static final long serialVersionUID = 4087954595439224462L; 
    private static final String password = "foobar1"; 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { 
     response.setContentType("application/vnd.ms-excel"); 
     response.addHeader("Content-Disposition", "attachment; filename=password_protected.xls"); 
     createAndWriteEncryptedWorkbook(response.getOutputStream()); 
    } 

    private void createAndWriteEncryptedWorkbook(OutputStream requestOutputStream) throws IOException { 
     HSSFWorkbook workbook = new HSSFWorkbook(); 
     populateWorkbook(workbook); 
     Biff8EncryptionKey.setCurrentUserPassword(password); 
     workbook.write(requestOutputStream); 
     workbook.close(); 
    } 

    private void populateWorkbook(Workbook workbook) { 
     workbook.createSheet("TestSheet"); 
     // TODO create other sheets, populate cell values 
    } 

} 

通过对/ workbook的请求,servlet使用名为TestSheet的工作表在内存中创建HSSF工作簿。密码设置为“foobar1”。它会提示浏览器将其作为名称为password_protected.xls的文件下载。

另见Apache POI - Encryption support。二进制格式(HSSF)的加密仅在Apache POI 3.16后才可用。在写这篇文章的时候,3.16还没有发布,在我的例子中我使用了3.16-beta1。

encyprtion支持指南还提供了创建加密(密码保护).xlsx(XSSF)文件的信息。这是我创建的一个例子,它会提示文件被命名为password_protected.xlsx:

package com.joshden; 

import java.io.IOException; 
import java.io.OutputStream; 
import java.security.GeneralSecurityException; 

import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.poi.openxml4j.opc.OPCPackage; 
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.Workbook; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

@WebServlet("/workbook") 
public class WorkbookServlet extends HttpServlet { 
    private static final long serialVersionUID = 4087954595439224462L; 
    private static final String password = "foobar1"; 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { 
     response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 
     response.addHeader("Content-Disposition", "attachment; filename=password_protected.xlsx"); 
     createAndWriteEncryptedWorkbook(response.getOutputStream()); 
    } 

    private void createAndWriteEncryptedWorkbook(OutputStream requestOutputStream) throws IOException { 
     XSSFWorkbook workbook = new XSSFWorkbook(); 
     OPCPackage opc = workbook.getPackage(); 
     populateWorkbook(workbook); 

     try { 
      POIFSFileSystem fileSystem = new POIFSFileSystem(); 
      opc.save(getEncryptingOutputStream(fileSystem, password)); 
      fileSystem.writeFilesystem(requestOutputStream); 
     } 
     finally { 
      workbook.close(); 
     } 
    } 

    private void populateWorkbook(Workbook workbook) { 
     workbook.createSheet("TestSheet"); 
     // TODO create other sheets, populate cell values 
    } 

    private OutputStream getEncryptingOutputStream(POIFSFileSystem fileSystem, String password) throws IOException { 
     EncryptionInfo encryptionInfo = new EncryptionInfo(EncryptionMode.agile); 
     Encryptor encryptor = encryptionInfo.getEncryptor(); 
     encryptor.confirmPassword(password); 

     try { 
      return encryptor.getDataStream(fileSystem); 
     } 
     catch (GeneralSecurityException e) { 
      // TODO handle this better 
      throw new RuntimeException(e); 
     } 
    } 

} 
+0

谢谢Joshden,我用apache3.15使用了XSSF第二个解决方案,它给了我下面的异常:我想我必须等待3.16 :) :javax.el.E​​LException:java.lang.NoSuchMethodError:org.apache.poi.poifs.crypt.EncryptionInfo。 (Lorg /阿帕奇/ POI/POIFS /隐窝/ EncryptionMode;)V \t在org.apache.el.parser.AstValue.invoke(AstValue.java:260) \t在org.apache.el.MethodExpressionImpl.invoke( MethodExpressionImpl.java:267) –

相关问题