1

I'm trying to upload an image file using h:inputFile tag and write it to disk.

My JSF code:

<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>

My 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());
      }
   }
}

Supposedly, the method write uploads item to disk and the IOException isn't throwed/catched too.

4

1 回答 1

8

The @javax.servlet.annotation.MultipartConfig annotation is supposed to be placed on the class implementing HttpServlet, not on a backing bean class. Basically, that annotation has to be placed on the FacesServlet class, which is already done since JSF 2.2.

In other words, the @MultipartConfig annotation on your backing bean class is being ignored and has no effect and the file is actually not saved in the location you specified in the annotation. Instead, it's been saved in a path relative to the so-called current working directory, which is basically the "currently opened folder" at the moment java.exe is been executed. In case of Java web applications that's usually server's binary folder or so. You can track it down as below:

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

You'll see your uploaded file there.

Moreover, even if the @MultipartConfig annotation did work, the location attribute does actually not represent the permanent file upload save location. Instead, it represents the temporary disk storage location for the case when the uploaded file size exceeds the available/configured memory space. You should never store uploaded files permanently at the location identified by @MultipartConfig(location). You should always obtain the file content via Part#getInputStream() and write it to the desired permanent location provided by a new File or Path representing an absolute path.

Get rid of that whole @MultipartConfig annotation. It's not doing anything useful in a backing bean class. Just obtain the file content by Part#getInputStream() and copy it to the desired absolute path:

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

See also


Unrelated to the concrete problem, using a session scoped bean for this purpose is not ideal. Rather use a view or request scoped one. See also How to choose the right bean scope? And, using prependId="false" is not recommended for other purposes than login forms tied to a login framework which doesn't support JSF-prepended ID in request parameter names. See also UIForm with prependId="false" breaks <f:ajax render>.

于 2013-08-30T13:13:57.510 回答