2016-12-28 94 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) –

相關問題