【问题标题】:Write file into disk using JSF 2.2 inputFile使用 JSF 2.2 inputFile 将文件写入磁盘
【发布时间】:2013-08-30 22:49:53
【问题描述】:

我正在尝试使用 h:inputFile 标签上传图像文件并将其写入磁盘。

我的 JSF 代码:

<h:form id="fileUploadForm" enctype='multipart/form-data' prependId="false">
   <h:inputFile value="#{solicitacaoManagedBean.imagemCarregada}" />
   <br />
   <h:commandButton styleClass="btn btn-primary " value="Enviar" action="#{solicitacaoManagedBean.enviarImagem}" />
</h:form>

我的 ManagedBean:

@Named(value = "solicitacaoManagedBean")
@SessionScoped
@MultipartConfig(location = "/home/rogerio/tmp/")
public class SolicitacaoManagedBean implements Serializable {

   private Part imagemCarregada;

(...)

   public void enviarImagem() throws IOException {
      try {
         imagemCarregada.write("teste.jpg");
      } catch (IOException ioe) {
         System.out.println("Erro ao escrever: " + ioe.getLocalizedMessage());
      }
   }
}

假设write方法将项目上传到磁盘并且IOException也没有被抛出/捕获。

【问题讨论】:

  • 是不是有些东西不工作?
  • 是的。该文件未写入磁盘。

标签: jsf file-upload file-io jsf-2.2


【解决方案1】:

@javax.servlet.annotation.MultipartConfig 注释应该放在实现HttpServlet 的类上,而不是放在后备 bean 类上。基本上,该注解必须放在 FacesServlet 类上,这从 JSF 2.2 开始就已经完成了。

换句话说,您的支持 bean 类上的 @MultipartConfig 注释被忽略并且没有效果,并且文件实际上没有保存在您在注释中指定的 location 中。相反,它被保存在相对于所谓的当前工作目录的路径中,这基本上是执行java.exe 时的“当前打开的文件夹”。对于 Java Web 应用程序,通常是服务器的二进制文件夹左右。您可以通过以下方式对其进行跟踪:

System.out.println(new File(".").getAbsolutePath());

您会在此处看到您上传的文件。

此外,即使@MultipartConfig 注释确实有效,location 属性实际上并不代表 永久 文件上传保存位置。相反,它表示当上传的文件大小超过可用/配置的内存空间时的临时磁盘存储位置。您永远不应将上传的文件永久存储在@MultipartConfig(location) 标识的位置。您应该始终通过Part#getInputStream() 获取文件内容并将其写入由代表绝对路径的新FilePath 提供的所需永久位置。

摆脱整个@MultipartConfig 注释。它在支持 bean 类中没有做任何有用的事情。只需通过Part#getInputStream()获取文件内容,复制到所需的绝对路径即可:

try (InputStream input = imagemCarregada.getInputStream()) {
    Files.copy(input, new File("/home/rogerio/tmp/teste.jpg").toPath());
}

另见


与具体问题无关,为此目的使用会话范围的 bean 并不理想。而是使用视图或请求范围的视图。另请参阅How to choose the right bean scope? 并且,不建议将prependId="false" 用于与不支持请求参数名称中的JSF 前缀ID 的登录框架绑定的登录表单之外的其他目的。另见UIForm with prependId="false" breaks <f:ajax render>

【讨论】:

  • 您应该始终通过 Part#write() 将其写入所需的永久位置 >> 你的意思是 Path#write() 吗?
  • @Mr_and_Mrs_D:不,Partjavax.servlet.http.Part。关于您当前的问题,另请参阅我的updated answer
  • 我猜这个:fileName - 将写入流的文件的名称。 该文件是相对于 MultipartConfig 中指定的位置创建的 docs 困惑我
  • 感谢@BalusC。现在我已经意识到 write() 方法将文件放在哪个目录中,但是即使指定了绝对路径,它也不起作用。抛出异常:java.io.FileNotFoundException: /srv/glassfish-4.0/glassfish/domains/domain1/generated/jsp/identidadeWeb-war/home/rogerio/teste.jpg。我会尝试另一种方式。
  • @rogerio_gentil: glassfish 显然不支持Part.write() 中的绝对文件路径:见here
猜你喜欢
  • 2013-03-05
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多