Como posso fazer upload de arquivos para o servidor usando JSP / Servlet? Eu tentei isso:
<form action="upload" method="post">
<input type="text" name="description" />
<input type="file" name="file" />
<input type="submit" />
</form>
No entanto, só recebo o nome do arquivo, não o conteúdo do arquivo. Quando adiciono enctype="multipart/form-data"
ao <form>
, request.getParameter()
retorna null
.
Durante a pesquisa, me deparei com o Apache Common FileUpload . Eu tentei isso:
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.
Infelizmente, o servlet lançou uma exceção sem uma mensagem e causa claras. Aqui está o stacktrace:
SEVERE: Servlet.service() for servlet UploadServlet threw exception
javax.servlet.ServletException: Servlet execution threw an exception
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:637)
java
jsp
jakarta-ee
servlets
file-upload
Thang Pham
fonte
fonte
Respostas:
Introdução
Para procurar e selecionar um arquivo para upload, você precisa de um
<input type="file">
campo HTML no formulário. Conforme declarado na especificação HTML, você deve usar oPOST
método e oenctype
atributo do formulário deve ser definido como"multipart/form-data"
.Depois de enviar esse formulário, os dados binários do formulário com várias partes ficam disponíveis no corpo da solicitação em um formato diferente do que quando
enctype
não está definido.Antes do Servlet 3.0, a API do Servlet não suportava nativamente
multipart/form-data
. Ele suporta apenas o tipo de formulário padrão deapplication/x-www-form-urlencoded
. Todos osrequest.getParameter()
consorts e retornariamnull
ao usar dados de formulário com várias partes. Foi aqui que o conhecido Apache Commons FileUpload entrou em cena.Não o analise manualmente!
Em teoria, você pode analisar o corpo da solicitação com base em
ServletRequest#getInputStream()
. No entanto, este é um trabalho preciso e tedioso que requer conhecimento preciso do RFC2388 . Você não deve tentar fazer isso sozinho ou copipar algum código caseiro sem biblioteca encontrado em outro lugar na Internet. Muitas fontes online falharam bastante nisso, como roseindia.net. Veja também o upload do arquivo pdf . Você deveria usar uma biblioteca real que é usada (e implicitamente testada!) Por milhões de usuários por anos. Essa biblioteca provou sua robustez.Quando você já estiver no Servlet 3.0 ou mais recente, use a API nativa
Se você estiver usando pelo menos o Servlet 3.0 (Tomcat 7, Jetty 9, JBoss AS 6, GlassFish 3, etc.), poderá usar a API padrão fornecida
HttpServletRequest#getPart()
para coletar os itens de dados de formulário de várias partes individuais (a maioria das implementações do Servlet 3.0 realmente usa Apache Commons FileUpload sob as capas para isso!). Além disso, os campos normais do formulário estão disponíveisgetParameter()
da maneira usual.Primeiro anote seu servlet
@MultipartConfig
para permitir que ele reconheça emultipart/form-data
dê suporte a solicitações e, assim, comecegetPart()
a trabalhar:Em seguida, implemente da
doPost()
seguinte maneira:Observe o
Path#getFileName()
. Esta é uma correção do MSIE para obter o nome do arquivo. Esse navegador envia incorretamente o caminho completo do arquivo ao longo do nome, em vez de apenas o nome do arquivo.Caso você tenha um
<input type="file" name="file" multiple="true" />
upload para vários arquivos, colete-os como abaixo (infelizmente não existe um método como esserequest.getParts("file")
):Quando você ainda não estiver no Servlet 3.1, obtenha manualmente o nome do arquivo enviado
Observe que
Part#getSubmittedFileName()
foi introduzido no Servlet 3.1 (Tomcat 8, Jetty 9, WildFly 8, GlassFish 4, etc.). Se você ainda não estiver no Servlet 3.1, precisará de um método utilitário adicional para obter o nome do arquivo enviado.Observe a correção do MSIE para obter o nome do arquivo. Esse navegador envia incorretamente o caminho completo do arquivo ao longo do nome, em vez de apenas o nome do arquivo.
Quando você ainda não estiver no Servlet 3.0, use o Apache Commons FileUpload
Se você ainda não está no Servlet 3.0 (não é hora de atualizar?), A prática comum é usar o Apache Commons FileUpload para analisar as solicitações de dados de formulário de várias partes. Possui um excelente Guia do Usuário e Perguntas frequentes (passe cuidadosamente por ambos). Há também o O'Reilly (" cos ")
MultipartRequest
, mas possui alguns bugs (menores) e não é mais mantido ativamente por anos. Eu não recomendaria usá-lo. O Apache Commons FileUpload ainda é mantido ativamente e atualmente está muito maduro.Para usar o Apache Commons FileUpload, você precisa ter pelo menos os seguintes arquivos nos aplicativos da web
/WEB-INF/lib
:commons-fileupload.jar
commons-io.jar
Sua tentativa inicial falhou muito provavelmente porque você esqueceu o IO comum.
Aqui está um exemplo de como o
doPost()
seuUploadServlet
pode parecer ao usar o Apache Commons FileUpload:É muito importante que você não chamar
getParameter()
,getParameterMap()
,getParameterValues()
,getInputStream()
,getReader()
, etc no mesmo pedido de antemão. Caso contrário, o contêiner do servlet lerá e analisará o corpo da solicitação e, portanto, o Apache Commons FileUpload receberá um corpo de solicitação vazio. Consulte também ao ServletFileUpload # parseRequest (request) retorna uma lista vazia .Observe o
FilenameUtils#getName()
. Esta é uma correção do MSIE para obter o nome do arquivo. Esse navegador envia incorretamente o caminho completo do arquivo ao longo do nome, em vez de apenas o nome do arquivo.Como alternativa, você também pode agrupar tudo em um
Filter
que analisa tudo automaticamente e colocar as coisas de volta no mapa de parâmetros da solicitação, para que você possa continuar usandorequest.getParameter()
a maneira usual e recuperar o arquivo enviado porrequest.getAttribute()
. Você pode encontrar um exemplo neste artigo do blog .Solução alternativa para o erro do GlassFish3 de
getParameter()
retornarnull
Observe que as versões do Glassfish anteriores à 3.1.2 tinham um erro no qual o
getParameter()
still ainda retornanull
. Se você estiver direcionando esse contêiner e não puder atualizá-lo, precisará extrair o valorgetPart()
com a ajuda deste método utilitário:Salvando o arquivo enviado (não use
getRealPath()
nempart.write()
!)Vá para as seguintes respostas para obter detalhes sobre como salvar corretamente o obtido
InputStream
(afileContent
variável mostrada nos trechos de código acima) em disco ou banco de dados:Servindo arquivo carregado
Vá para as seguintes respostas para obter detalhes sobre como enviar corretamente o arquivo salvo do disco ou banco de dados para o cliente:
Ajaxificando o formulário
Vá para as respostas a seguir como fazer upload usando o Ajax (e jQuery). Observe que o código do servlet para coletar os dados do formulário não precisa ser alterado para isso! Somente a maneira como você responde pode ser alterada, mas isso é bastante trivial (ou seja, em vez de encaminhar para JSP, basta imprimir algum JSON ou XML ou mesmo texto sem formatação, dependendo do que o script responsável pela chamada do Ajax estiver esperando).
Espero que tudo isso ajude :)
fonte
request.getParts("file")
e foi confundido x_xMultipartConfig
condição for violada (por exemplomaxFileSize
:), a chamadarequest.getParameter()
retornará nulo. Isso é de propósito? E se eu receber alguns parâmetros regulares (texto) antes de chamargetPart
(e procurar por umIllegalStateException
)? Isso faz com que umNullPointerException
seja lançado antes que eu tenha a chance de verificar oIllegalStateException
.String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
parte semelhante a mimSe você usa o Spring MVC, é assim: (vou deixar isso aqui caso alguém ache útil).
Use um formulário com
enctype
atributo definido como "multipart/form-data
" (Igual à resposta do BalusC)No seu controlador, mapeie o parâmetro request
file
paraMultipartFile
digitar da seguinte maneira:Você pode obter o nome do arquivo e o tamanho usando
MultipartFile
'sgetOriginalFilename()
egetSize()
.Eu testei isso com a versão Spring
4.1.1.RELEASE
.fonte
Você precisa que o
common-io.1.4.jar
arquivo seja incluído no seulib
diretório ou, se estiver trabalhando em algum editor, como o NetBeans, precisará ir às propriedades do projeto e apenas adicionar o arquivo JAR e pronto.Para obter o
common.io.jar
arquivo, basta pesquisar no Google ou acessar o site do Apache Tomcat , onde você tem a opção de fazer o download gratuito desse arquivo. Mas lembre-se de uma coisa: baixe o arquivo ZIP binário se você for um usuário do Windows.fonte
.jar
mas.zip
. Você quer dizer.zip
?Sem componente ou biblioteca externa no Tomcat 6 ou 7
Ativando o Upload no arquivo web.xml :
http://joseluisbz.wordpress.com/2014/01/17/manually-installing-php-tomcat-and-httpd-lounge/#Enabled%20File%20Uploads .
COMO VOCÊ PODE VER :
Fazendo upload de arquivos usando JSP. Arquivos:
No arquivo html
No arquivo JSP ou no servlet
Editar seu código aos requisitos do servlet, como o arquivo de tamanho máximo , max-pedido de tamanho e outras opções que você pode definir ...
fonte
Estou usando o Servlet comum para todos os formulários HTML, tenham ou não anexos. Este Servlet retorna um local
TreeMap
onde as chaves são jsp name Parâmetros e valores são Entradas do usuário e salva todos os anexos no diretório fixo e, posteriormente, você renomeia o diretório de sua escolha. Aqui Connections é a nossa interface personalizada com objeto de conexão. Eu acho que isso vai te ajudarfonte
Para o Spring MVC, venho tentando há horas fazer isso e consegui ter uma versão mais simples que funcionava para assumir a entrada de formulário, dados e imagem.
Controlador para manusear
Espero que ajude :)
fonte
Outra fonte desse problema ocorre se você estiver usando o Geronimo com o Tomcat incorporado. Nesse caso, depois de muitas iterações de teste do commons-io e commons-fileupload, o problema surge de um carregador de classe pai manipulando os jars commons-xxx. Isso tem que ser evitado. A falha sempre ocorria em:
Observe que o tipo de lista de fileItems foi alterado com a versão atual do commons-fileupload para ser especificamente diferente das
List<FileItem>
versões anteriores em que era genéricoList
.Adicionei o código-fonte para commons-fileupload e commons-io no meu projeto Eclipse para rastrear o erro real e finalmente obtive algumas dicas. Primeiro, a exceção lançada é do tipo Throwable, não a FileIOException declarada nem a Exception (elas não serão interceptadas). Segundo, a mensagem de erro é ofuscante, pois afirmou que a classe não foi encontrada porque o eixo2 não pôde encontrar o commons-io. O Axis2 não é usado no meu projeto, mas existe como uma pasta no subdiretório do repositório Geronimo como parte da instalação padrão.
Finalmente, encontrei um lugar que apresentava uma solução funcional que resolveu meu problema com êxito. Você deve ocultar os frascos do carregador pai no plano de implantação. Isso foi colocado em geronimo-web.xml com meu arquivo completo mostrado abaixo.
fonte
Aqui está um exemplo usando o apache commons-fileupload:
fonte
A maneira mais simples seria criar arquivos e controles de entrada, sem um bilhão de bibliotecas:
fonte
você pode fazer upload de arquivo usando jsp / servlet.
por outro lado, do servidor. use o seguinte código.
fonte
A partir deste objeto, você precisa obter itens e campos de arquivo, para que possa armazenar no servidor da seguinte maneira:
fonte
Enviando vários arquivos por arquivo, temos que usar
enctype="multipart/form-data"
e enviar vários arquivos
multiple="multiple"
na tag de entradafonte
PÁGINA HTML
ARQUIVO DE SERVLET
web.xml
Compile acima do servlet UploadServlet e crie a entrada necessária no arquivo web.xml da seguinte maneira.
fonte