1

我有一个为客户端生成 docx 文件的按钮。我遇到的问题是生成的文件交给客户端后无法删除。服务器端技术是 JSF (XPages)。该按钮调用以下代码:

var v = new ru.generate.doc.generateDoc();
v.generateReport2();

generateReport2()方法调用 2 个重要方法generateFromTemplateAndReturnPath(String template)

private String generateFromTemplateAndReturnPath(String pathToTemplate) 
{
          XWPFDocument document = new XWPFDocument(OPCPackage.open(pathToTemplate));
          String pathToFinalResult = FilenameUtils.getFullPath(pathToTemplate) + "reportTest.docx";
          FileOutputStream fous = new FileOutputStream(pathToFinalResult);
          document.write(fous);
          fous.close();
          return pathToFinalResult;
}

以及将giveDocumentForClient(String pathToCompleteFile)报告提供给客户的方法:

private void giveDocumentForClient(String pathToCompleteFile) throws InvalidFormatException, IOException 
{
      String fn = new File(pathToCompleteFile).getName();
      XspHttpServletResponse response = (XspHttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
      response.setContentType(URLConnection.guessContentTypeFromName(fn));
      response.setHeader("Content-disposition", "attachment; filename=" + fn);
      OutputStream output = response.getOutputStream();
      output.write(IOUtils.toByteArray(new FileInputStream(new File(pathToCompleteFile))));
      output.close();
      FacesContext.getCurrentInstance().responseComplete(); 
}

完成此方法后,我尝试在内部进行此操作generateReport2()

new File(pathToCompleteFile).delete()

无论我做什么,这个方法都会返回 false。我也试过:

FileDeleteStrategy.FORCE.delete(new File(pathToSubstitutedDoc))

但还是没有结果。

canRead()、canWrite()、canExecute() 等方法总是返回 true。SecurityManager 也毫无例外地执行方法。问题是什么?

4

2 回答 2

2

嗯,这真的很简单。我忘记了 FileInputStream 也应该关闭。

该方法应如下所示:

private void giveDocumentForClient(String pathToCompleteFile) throws InvalidFormatException, IOException 
{
      FileInputStream fis = new FileInputStream(new File(pathToCompleteFile));
      String fn = new File(pathToCompleteFile).getName();
      XspHttpServletResponse response = (XspHttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
      response.setContentType(URLConnection.guessContentTypeFromName(fn));
      response.setHeader("Content-disposition", "attachment; filename=" + fn);
      OutputStream output = response.getOutputStream();
      output.write(IOUtils.toByteArray(fis));
      output.close();
      fis.close();
      FacesContext.getCurrentInstance().responseComplete(); 
}
于 2018-07-16T09:03:38.247 回答
1

您可以尝试更好的 Files 类:

  OutputStream output = response.getOutputStream();
  Files.copy(Paths.get(pathToCompleteFile), output);

  Files.delete(Paths.get(pathToCompleteFile));

虽然这可能并不能解决问题。

如果不可删除,则文件在其生成期间未关闭。由于应用程序仍在运行,因此会维护文件句柄。在 Windows 下尤其如此。

(或者这将是文件权限的问题。但是您检查了:SecurityManagercanRead。)

然后是一些深奥的案例,比如病毒扫描程序


在查看生成代码之后;做:

      try (FileOutputStream fous = new FileOutputStream(pathToFinalResult)) {
          document.write(fous);
      } // Automatic fous.close() even on exception or return.

这种 try-with-resources 确保自动关闭,即使在异常/中断/返回时也是如此。

于 2018-07-16T07:49:45.657 回答