Como configurar e solucionar problemas <p:fileUpload>
depende da versão do PrimeFaces.
Todas as versões PrimeFaces
Os requisitos abaixo se aplicam a todas as versões PrimeFaces:
O enctype
atributo de <h:form>
precisa ser definido como multipart/form-data
. Quando isso está ausente, o upload de ajax pode funcionar, mas o comportamento geral do navegador não é especificado e depende da composição do formulário e da marca / versão do navegador da web. Apenas sempre especifique para estar no lado seguro.
Ao usar mode="advanced"
(isto é, upload de ajax, este é o padrão), certifique-se de ter um <h:head>
no modelo (mestre). Isso garantirá que os arquivos JavaScript necessários sejam incluídos corretamente. Isso não é necessário para mode="simple"
(upload não ajax), mas quebraria a aparência e a funcionalidade de todos os outros componentes do PrimeFaces, então você não vai querer perder isso de qualquer maneira.
Ao usar mode="simple"
(ou seja, upload não ajax), o ajax deve ser desabilitado em qualquer botão / link de comando PrimeFaces por ajax="false"
, e você deve usar <p:fileUpload value>
com em <p:commandButton action>
vez de <p:fileUpload fileUploadListener>
(para PrimeFaces <= 7.x) ou <p:fileUpload listener>
(para PrimeFaces> = 8.x)
Então, se você quiser upload (automático) de arquivo com suporte ajax (lembre-se <h:head>
!):
<h:form enctype="multipart/form-data">
<p:fileUpload fileUploadListener="#{bean.upload}" auto="true" /> // for PrimeFaces >= 8.x this should be listener instead of fileUploadListener
</h:form>
public void upload(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
Ou se você quiser um upload de arquivo não ajax:
<h:form enctype="multipart/form-data">
<p:fileUpload mode="simple" value="#{bean.uploadedFile}" />
<p:commandButton value="Upload" action="#{bean.upload}" ajax="false" />
</h:form>
private UploadedFile uploadedFile; // +getter+setter
public void upload() {
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
Note que os atributos relacionados com o Ajax, como auto
, allowTypes
, update
, onstart
, oncomplete
, etc são ignorados no mode="simple"
. Portanto, não é necessário especificá-los nesse caso.
Observe também que você deve ler o conteúdo do arquivo imediatamente dentro dos métodos mencionados acima e não em um método de bean diferente chamado por uma solicitação HTTP posterior. Isso ocorre porque o conteúdo do arquivo carregado tem escopo de solicitação e, portanto, não está disponível em uma solicitação HTTP posterior / diferente. Qualquer tentativa de lê-lo em uma solicitação posterior provavelmente terminará java.io.FileNotFoundException
no arquivo temporário.
PrimeFaces 8.x
A configuração é idêntica às informações da versão 5.x abaixo, mas se seu ouvinte não for chamado, verifique se o atributo é chamado listener
e não (como nas versões anteriores a 8.x)fileUploadListener
PrimeFaces 5.x
Isso não requer nenhuma configuração adicional se você estiver usando JSF 2.2 e sua faces-config.xml
versão JSF 2.2 também for declarada. Você não precisa do filtro de upload de arquivo PrimeFaces. Caso não esteja claro para você como instalar e configurar corretamente o JSF dependendo do servidor de destino usado, vá para Como instalar e configurar corretamente as bibliotecas JSF via Maven? e a seção "Instalando JSF" de nossa página wiki JSF .
No entanto, se você ainda não estiver usando o JSF 2.2 e não puder atualizá-lo (deve ser fácil quando já estiver em um contêiner compatível com Servlet 3.0), então você precisa registrar manualmente o filtro de upload de arquivo PrimeFaces abaixo web.xml
(ele irá analisar o multi solicitar parte e preencher o mapa de parâmetros de solicitação regular para que FacesServlet
possa continuar trabalhando normalmente):
<filter>
<filter-name>primeFacesFileUploadFilter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
</filter-mapping>
O <servlet-name>
valor de facesServlet
deve corresponder exatamente ao valor na <servlet>
entrada do javax.faces.webapp.FacesServlet
mesmo web.xml
. Portanto, se for por exemplo Faces Servlet
, você precisa editá-lo de acordo para corresponder.
PrimeFaces 4.x
A mesma história do PrimeFaces 5.x também se aplica ao 4.x.
Há apenas um problema potencial em obter o conteúdo do arquivo carregado por UploadedFile#getContents()
. Isso retornará null
quando a API nativa for usada em vez do Apache Commons FileUpload. Você precisa usar em seu UploadedFile#getInputStream()
lugar. Veja também Como inserir imagem enviada de p: fileUpload como BLOB no MySQL?
Outro problema potencial com a API nativa se manifestará quando o componente de upload estiver presente em um formato no qual uma solicitação ajax "normal" diferente é disparada, o que não processa o componente de upload. Veja também O upload de arquivo não funciona com AJAX em PrimeFaces 4.0 / JSF 2.2.x - javax.servlet.ServletException: O tipo de conteúdo da solicitação não é multipart / form-data .
Ambos os problemas também podem ser resolvidos mudando para o Apache Commons FileUpload. Consulte a seção PrimeFaces 3.x para obter detalhes.
PrimeFaces 3.x
Esta versão não suporta upload de arquivo nativo JSF 2.2 / Servlet 3.0. Você precisa instalar manualmente o Apache Commons FileUpload e registrar explicitamente o filtro de upload de arquivo em web.xml
.
Você precisa das seguintes bibliotecas:
Eles devem estar presentes no classpath do tempo de execução do webapp. Ao usar o Maven, certifique-se de que tenham pelo menos escopo de tempo de execução (o escopo padrão de compilação também é bom). Ao transportar JARs manualmente, certifique-se de que eles acabem na /WEB-INF/lib
pasta.
Os detalhes do registro do filtro de upload de arquivo podem ser encontrados na seção PrimeFaces 5.x aqui acima. Caso você esteja usando PrimeFaces 4+ e gostaria de usar explicitamente o Apache Commons FileUpload em vez de upload de arquivo nativo JSF 2.2 / Servlet 3.0, você precisa ao lado das bibliotecas mencionadas e filtrar também o parâmetro de contexto abaixo em web.xml
:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
Solução de problemas
Caso ainda não funcione, aqui estão outras possíveis causas não relacionadas à configuração do PrimeFaces:
Só se você estiver usando o filtro de upload do arquivo PrimeFaces: Há um outro Filter
em sua webapp que corre antes do filtro de upload do arquivo PrimeFaces e já consumiu o corpo de solicitação por exemplo vocação getParameter()
, getParameterMap()
, getReader()
, etcetera. Um corpo de solicitação pode ser analisado apenas uma vez. Quando você chama um desses métodos antes que o filtro de upload de arquivo faça seu trabalho, o filtro de upload de arquivo obterá um corpo de solicitação vazio.
Para corrigir isso, você precisa colocar o <filter-mapping>
do filtro de upload de arquivo antes do outro filtro em web.xml
. Se a solicitação não for uma multipart/form-data
solicitação, o filtro de upload de arquivo continuará como se nada tivesse acontecido. Se você usar filtros que são adicionados automaticamente porque usam anotações (por exemplo, PrettyFaces), pode ser necessário adicionar ordenação explícita via web.xml. Veja Como definir a ordem de execução do filtro de servlet usando anotações no WAR
Somente se você estiver usando o filtro de upload de arquivo PrimeFaces: há outro Filter
em seu webapp que é executado antes do filtro de upload de arquivo PrimeFaces e realizou uma RequestDispatcher#forward()
chamada. Normalmente, os filtros de reescrita de URL, como PrettyFaces, fazem isso. Isso aciona o FORWARD
despachante, mas os filtros ouvem por padrão REQUEST
apenas no despachante.
Para corrigir isso, você precisa colocar o filtro de upload de arquivo PrimeFaces antes do filtro de encaminhamento ou reconfigurar o filtro de upload de arquivo PrimeFaces para ouvir no FORWARD
dispatcher também:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Há um aninhado <h:form>
. Isso é ilegal em HTML e o comportamento do navegador não é especificado. Mais do que frequentemente, o navegador não envia os dados esperados ao enviar. Certifique-se de que você não está aninhando <h:form>
. Isso é completamente independente do formulário enctype
. Simplesmente não aninhe formas.
Se ainda estiver tendo problemas, depure o tráfego HTTP. Abra o conjunto de ferramentas do desenvolvedor do navegador (pressione F12 no Chrome / Firebug23 + / IE9 +) e verifique a seção Rede / Rede. Se a parte HTTP parecer boa, depure o código JSF. Coloque um ponto de interrupção FileUploadRenderer#decode()
e avance a partir daí.
Salvando arquivo enviado
Depois que você finalmente começar a trabalhar, sua próxima pergunta provavelmente será como "Como / onde eu salvo o arquivo enviado?". Bem, continue aqui: Como salvar o arquivo carregado no JSF .
web.xml
acordo com o Guia do Usuário PrimeFaces. Você leu mesmo assim? No entanto, isso não explicaria por quemode="simple"
funciona para você.