¿Cómo puedo subir archivos al servidor usando JSP / Servlet? Intenté esto:
<form action="upload" method="post">
<input type="text" name="description" />
<input type="file" name="file" />
<input type="submit" />
</form>
Sin embargo, solo obtengo el nombre del archivo, no el contenido del archivo. Cuando agrego enctype="multipart/form-data"
a la <form>
, entoncesrequest.getParameter()
regresa null
.
Durante la investigación me topé con Apache Common FileUpload . Intenté esto:
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.
Desafortunadamente, el servlet arrojó una excepción sin un mensaje claro y una causa. Aquí está el 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
fuente
fuente
Respuestas:
Introducción
Para examinar y seleccionar un archivo para cargar, necesita un
<input type="file">
campo HTML en el formulario. Como se indica en la especificación HTML , debe usar elPOST
método y elenctype
atributo del formulario debe establecerse en"multipart/form-data"
.Después de enviar dicho formulario, los datos del formulario multiparte binario están disponibles en el cuerpo de la solicitud en un formato diferente al que
enctype
no está configurado.Antes de Servlet 3.0, la API de Servlet no era compatible de forma nativa
multipart/form-data
. Solo admite el tipo de formulario predeterminado deapplication/x-www-form-urlencoded
. Elrequest.getParameter()
y consortes habría todos regresannull
al utilizar los datos del formulario de varias partes. Aquí es donde el conocido Apache Commons FileUpload entró en escena la .¡No lo analices manualmente!
En teoría, puede analizar el cuerpo de la solicitud en función de
ServletRequest#getInputStream()
. Sin embargo, este es un trabajo preciso y tedioso que requiere un conocimiento preciso de RFC2388 . No debe intentar hacer esto por su cuenta o copiar un código sin biblioteca propio que se encuentre en otra parte de Internet. Muchas fuentes en línea han fallado mucho en esto, como roseindia.net. Consulte también carga de archivo pdf . Debería utilizar una biblioteca real que millones de usuarios usan (¡y se prueban implícitamente!) Durante años. Dicha biblioteca ha demostrado su robustez.Cuando ya esté en Servlet 3.0 o más reciente, use API nativa
Si está utilizando al menos Servlet 3.0 (Tomcat 7, Jetty 9, JBoss AS 6, GlassFish 3, etc.), puede usar la API estándar provista
HttpServletRequest#getPart()
para recopilar los elementos de datos de formularios individuales (la mayoría de las implementaciones de Servlet 3.0 en realidad usan Apache Commons FileUpload debajo de las cubiertas para esto!). Además, los campos de formulario normales están disponibles degetParameter()
la manera habitual.Primero anote su servlet con el
@MultipartConfig
fin de permitirle reconocer y admitirmultipart/form-data
solicitudes y así ponersegetPart()
a trabajar:Luego, implemente
doPost()
lo siguiente:Tenga en cuenta el
Path#getFileName()
. Esta es una solución de MSIE para obtener el nombre del archivo. Este navegador envía incorrectamente la ruta completa del archivo a lo largo del nombre en lugar de solo el nombre del archivo.En caso de que tenga una
<input type="file" name="file" multiple="true" />
carga de varios archivos, recójalos de la siguiente manera (desafortunadamente no existe tal métodorequest.getParts("file")
):Cuando aún no esté en Servlet 3.1, obtenga manualmente el nombre del archivo enviado
Tenga en cuenta que
Part#getSubmittedFileName()
se introdujo en Servlet 3.1 (Tomcat 8, Jetty 9, WildFly 8, GlassFish 4, etc.). Si aún no está en Servlet 3.1, necesita un método de utilidad adicional para obtener el nombre del archivo enviado.Tenga en cuenta la corrección de MSIE para obtener el nombre del archivo. Este navegador envía incorrectamente la ruta completa del archivo a lo largo del nombre en lugar de solo el nombre del archivo.
Cuando aún no esté en Servlet 3.0, use Apache Commons FileUpload
Si aún no está en Servlet 3.0 (¿no es hora de actualizar?), La práctica común es utilizar Apache Commons FileUpload para analizar las solicitudes de datos de formularios de varias partes. Tiene una excelente Guía del usuario y preguntas frecuentes ( revise cuidadosamente ambas). También está el O'Reilly (" cos ")
MultipartRequest
, pero tiene algunos errores (menores) y ya no se mantiene activamente durante años. No recomendaría usarlo. Apache Commons FileUpload todavía se mantiene activamente y actualmente es muy maduro.Para utilizar Apache Commons FileUpload, debe tener al menos los siguientes archivos en su aplicación web
/WEB-INF/lib
:commons-fileupload.jar
commons-io.jar
Su intento inicial falló muy probablemente porque olvidó los IO comunes.
Aquí hay un ejemplo inicial de cómo puede ser
doPost()
tuUploadServlet
cuando usas Apache Commons FileUpload:Es muy importante que usted no llama
getParameter()
,getParameterMap()
,getParameterValues()
,getInputStream()
,getReader()
, etc en la misma solicitud de antemano. De lo contrario, el contenedor de servlet leerá y analizará el cuerpo de la solicitud y, por lo tanto, Apache Commons FileUpload obtendrá un cuerpo de solicitud vacío. Consulte también ao ServletFileUpload # parseRequest (request) devuelve una lista vacía .Tenga en cuenta el
FilenameUtils#getName()
. Esta es una solución de MSIE para obtener el nombre del archivo. Este navegador envía incorrectamente la ruta completa del archivo a lo largo del nombre en lugar de solo el nombre del archivo.Alternativamente, también puede envolver todo esto de manera
Filter
que lo analice todo automáticamente y vuelva a colocar el material en el mapa de parámetros de la solicitud para que pueda continuar utilizandorequest.getParameter()
la forma habitual y recuperar el archivo cargadorequest.getAttribute()
. Puedes encontrar un ejemplo en este artículo de blog .Solución alternativa para el error GlassFish3 de
getParameter()
volver aúnnull
Tenga en cuenta que las versiones de Glassfish anteriores a 3.1.2 tenían un error en el que
getParameter()
aún se devuelvenull
. Si está apuntando a dicho contenedor y no puede actualizarlo, entonces necesita extraer el valorgetPart()
con la ayuda de este método de utilidad:Guardando el archivo cargado (¡no use
getRealPath()
nipart.write()
!)Diríjase a las siguientes respuestas para obtener detalles sobre cómo guardar correctamente el obtenido
InputStream
(lafileContent
variable como se muestra en los fragmentos de código anteriores) en el disco o la base de datos:Sirviendo archivos cargados
Diríjase a las siguientes respuestas para obtener detalles sobre cómo servir correctamente el archivo guardado desde el disco o la base de datos al cliente:
Ajaxificando el formulario
Diríjase a las siguientes respuestas sobre cómo cargar usando Ajax (y jQuery). ¡Tenga en cuenta que el código de servlet para recopilar los datos del formulario no necesita ser cambiado para esto! Solo se puede cambiar la forma en que responde, pero esto es bastante trivial (es decir, en lugar de reenviar a JSP, simplemente imprima JSON o XML o incluso texto sin formato dependiendo de lo que el script responsable de la llamada Ajax esté esperando).
Espero que todo esto ayude :)
fuente
request.getParts("file")
y estaba confundido x_xMultipartConfig
se viola una condición (por ejemplomaxFileSize
:), la llamadarequest.getParameter()
devuelve nulo. ¿Es esto a propósito? ¿Qué sucede si obtengo algunos parámetros regulares (de texto) antes de llamargetPart
(y buscar unIllegalStateException
)? Esto haceNullPointerException
que se lance un archivo antes de que tenga la oportunidad de verificarloIllegalStateException
.String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
parte similar a míSi usa Spring MVC, así es como: (Dejo esto aquí en caso de que alguien lo encuentre útil).
Utilice un formulario con el
enctype
atributo establecido en "multipart/form-data
" (igual que la respuesta de BalusC)En su controlador, asigne el parámetro de solicitud
file
paraMultipartFile
escribir de la siguiente manera:Puede obtener el nombre de archivo y el tamaño usando
MultipartFile
'sgetOriginalFilename()
ygetSize()
.He probado esto con la versión Spring
4.1.1.RELEASE
.fuente
Necesita que el
common-io.1.4.jar
archivo se incluya en sulib
directorio, o si está trabajando en cualquier editor, como NetBeans, debe ir a las propiedades del proyecto y simplemente agregar el archivo JAR y listo.Para obtener el
common.io.jar
archivo, simplemente búscalo en Google o simplemente ve al sitio web de Apache Tomcat , donde obtienes la opción de descargarlo gratuitamente. Pero recuerde una cosa: descargue el archivo ZIP binario si es un usuario de Windows.fuente
.jar
pero.zip
. Qué quiere decir.zip
?Sin componente o biblioteca externa en Tomcat 6 o 7
Habilitar la carga en el archivo web.xml :
http://joseluisbz.wordpress.com/2014/01/17/manually-installing-php-tomcat-and-httpd-lounge/#Enabling%20File%20Uploads .
COMO PUEDES VER :
Carga de archivos usando JSP. Archivos:
En el archivo html
En el archivo JSP o Servlet
Edite su código según los requisitos del servlet, como max-file-size , max-request-size y otras opciones que puede configurar ...
fuente
Estoy usando Servlet común para cada formulario HTML, ya sea que tenga archivos adjuntos o no. Este Servlet devuelve un lugar
TreeMap
donde las claves son jsp name Los parámetros y los valores son Entradas de usuario y guarda todos los archivos adjuntos en un directorio fijo y luego cambia el nombre del directorio de su elección. Aquí Connections es nuestra interfaz personalizada que tiene un objeto de conexión. Creo que esto te ayudaráfuente
Para Spring MVC , he estado intentando durante horas hacer esto y logré tener una versión más simple que funcionó para tomar la entrada de datos y la imagen.
Controlador para manejar
Espero eso ayude :)
fuente
Otra fuente de este problema ocurre si está utilizando Geronimo con su Tomcat incorporado. En este caso, después de muchas iteraciones de probar commons-io y commons-fileupload, el problema surge de un cargador de clases padre que maneja los frascos commons-xxx. Esto tiene que ser prevenido. El choque siempre ocurrió a las:
Tenga en cuenta que el tipo de lista de elementos de archivo ha cambiado con la versión actual de commons-fileupload para ser específicamente
List<FileItem>
opuesta a las versiones anteriores donde era genéricaList
.Agregué el código fuente de commons-fileupload y commons-io en mi proyecto Eclipse para rastrear el error real y finalmente obtuve una idea. Primero, la excepción lanzada es de tipo Throwable, no la FileIOException establecida ni la Excepción (estas no quedarán atrapadas). En segundo lugar, el mensaje de error es ofuscatorio porque indica que la clase no se encuentra porque axis2 no pudo encontrar commons-io. Axis2 no se utiliza en mi proyecto, pero existe como una carpeta en el subdirectorio del repositorio de Geronimo como parte de la instalación estándar.
Finalmente, encontré 1 lugar que planteaba una solución de trabajo que resolvió con éxito mi problema. Debe ocultar los archivos jar del cargador principal en el plan de implementación. Esto se puso en geronimo-web.xml con mi archivo completo que se muestra a continuación.
fuente
Aquí hay un ejemplo usando apache commons-fileupload:
fuente
La forma más sencilla podría ser para archivos y controles de entrada, sin un billón de bibliotecas:
fuente
puedes subir archivos usando jsp / servlet.
por otro lado del servidor. use el siguiente código.
fuente
De este objeto, debe obtener elementos de archivo y campos, luego puede almacenarlos en el servidor de la siguiente manera:
fuente
Enviar múltiples archivos por archivo que tenemos que usar
enctype="multipart/form-data"
y enviar el uso de múltiples archivos
multiple="multiple"
en la etiqueta de entradafuente
PÁGINA HTML
ARCHIVO DE SERVLET
web.xml
Compile el servlet UploadServlet anterior y cree la entrada requerida en el archivo web.xml de la siguiente manera.
fuente