Saltar al contenido

¿Cómo subir archivos al servidor usando JSP / Servlet?

Este equipo de especialistas despúes de ciertos días de trabajo y recopilar de información, hemos dado con los datos necesarios, deseamos que resulte de gran utilidad en tu trabajo.

Solución:

Introducción

Para buscar y seleccionar un archivo para cargar, necesita un HTML campo en el formulario. Como se indica en la especificación HTML, debe utilizar el POST método y el enctype attribute del formulario debe establecerse en "multipart/form-data".

Después de enviar dicho formulario, los datos del formulario binario de varias partes están disponibles en el cuerpo de la solicitud en un formato diferente al 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 de application/x-www-form-urlencoded. los request.getParameter() y todas las consortes volverían null cuando se utilizan datos de formularios de varias partes. Aquí es donde entró en escena el conocido Apache Commons FileUpload.

¡No lo analice manualmente!

En teoría, puede analizar el cuerpo de la solicitud usted mismo 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 y pegar un código sin biblioteca de cosecha propia que se encuentra en otros lugares de Internet. Muchas fuentes en línea han fracasado mucho en esto, como roseindia.net. Consulte también carga de archivo pdf. En su lugar, debería utilizar una biblioteca real que sea utilizada (¡y probada implícitamente!) Por millones de usuarios durante años. Una biblioteca de este tipo ha demostrado su solidez.

Cuando ya esté en Servlet 3.0 o más reciente, use la 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 proporcionada HttpServletRequest#getPart() para recopilar los elementos de datos de formularios de varias partes 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 por getParameter() de la forma habitual.

Primero anote su servlet con @MultipartConfig para que reconozca y apoye multipart/form-data solicitudes y así obtener getPart() trabajar:

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet 
    // ...

Luego, implemente su doPost() como sigue:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    String description = request.getParameter("description"); // Retrieves 
    Part filePart = request.getPart("file"); // Retrieves 
    String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
    InputStream fileContent = filePart.getInputStream();
    // ... (do your job here)

Nota la 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 junto con el nombre en lugar de solo el nombre del archivo.

En caso de que tenga un para la carga de varios archivos, recójalos como se muestra a continuación (desafortunadamente no existe un método como request.getParts("file")):

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    // ...
    List fileParts = request.getParts().stream().filter(part -> "file".equals(part.getName()) && part.getSize() > 0).collect(Collectors.toList()); // Retrieves 

    for (Part filePart : fileParts) 
        String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
        InputStream fileContent = filePart.getInputStream();
        // ... (do your job here)
    

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, entonces necesita un método de utilidad adicional para obtener el nombre del archivo enviado.

private static String getSubmittedFileName(Part part) 
    for (String cd : part.getHeader("content-disposition").split(";")) 
        if (cd.trim().startsWith("filename")) 
            String fileName = cd.substring(cd.indexOf('=') + 1).trim().replace(""", "");
            return fileName.substring(fileName.lastIndexOf('/') + 1).substring(fileName.lastIndexOf('\') + 1); // MSIE fix.
        
    
    return null;

String fileName = getSubmittedFileName(filePart);

Tenga en cuenta la corrección de MSIE para obtener el nombre del archivo. Este navegador envía incorrectamente la ruta completa del archivo junto con el 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 hacer uso de 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 ambas con cuidado). 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 está 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ó el IO común.

Aquí hay un ejemplo de inicio de cómo doPost() de tu UploadServlet puede verse como cuando se usa Apache Commons FileUpload:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    try 
        List items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
        for (FileItem item : items) 
            if (item.isFormField()) etc", select, etc).
                String fieldName = item.getFieldName();
                String fieldValue = item.getString();
                // ... (do your job here)
             else 
                // Process form file field (input type="file").
                String fieldName = item.getFieldName();
                String fileName = FilenameUtils.getName(item.getName());
                InputStream fileContent = item.getInputStream();
                // ... (do your job here)
            
        
     catch (FileUploadException e) 
        throw new ServletException("Cannot parse multipart request.", e);
    

    // ...

Es muy importante que no llames getParameter(), getParameterMap(), getParameterValues(), getInputStream(), getReader(), etc.en la misma solicitud de antemano. De lo contrario, el contenedor de servlets 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 (solicitud) devuelve una lista vacía.

Nota la 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 junto con el nombre en lugar de solo el nombre del archivo.

Alternativamente, también puede envolver todo esto en un Filter que analiza todo automágicamente y vuelve a colocar las cosas en el mapa de parámetros de la solicitud para que pueda continuar usando request.getParameter() de la forma habitual y recupere el archivo cargado por request.getAttribute(). Puede encontrar un ejemplo en este artículo de blog.

Solución alternativa para el error GlassFish3 de getParameter() todavía regresando null

Tenga en cuenta que las versiones de Glassfish anteriores a la 3.1.2 tenían un error en el que getParameter() todavía regresa null. Si está apuntando a un contenedor de este tipo y no puede actualizarlo, debe extraer el valor de getPart() con la ayuda de este método de utilidad:

private static String getValue(Part part) throws IOException 
    BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), "UTF-8"));
    StringBuilder value = new StringBuilder();
    char[] buffer = new char[1024];
    for (int length = 0; (length = reader.read(buffer)) > 0;) 
        value.append(buffer, 0, length);
    
    return value.toString();

String description = getValue(request.getPart("description")); // Retrieves 

Guardando el archivo subido (no usar getRealPath() ni part.write()!)

Diríjase a las siguientes respuestas para obtener detalles sobre cómo guardar correctamente los datos obtenidos. InputStream (los fileContent variable como se muestra en los fragmentos de código anteriores) al disco o base de datos:

  • Forma recomendada de guardar archivos cargados en una aplicación de servlet
  • ¿Cómo subir una imagen y guardarla en la base de datos?
  • ¿Cómo convertir Part a Blob, para poder almacenarlo en MySQL?

Sirviendo el archivo subido

Diríjase a las siguientes respuestas para obtener detalles sobre cómo entregar correctamente el archivo guardado desde el disco o la base de datos al cliente:

  • Cargue imágenes desde fuera de la carpeta webapps / webcontext / deploy usando o
    etiqueta
  • ¿Cómo recuperar y mostrar imágenes de una base de datos en una página JSP?
  • La forma más sencilla de servir static datos de fuera del servidor de aplicaciones en una aplicación web Java
  • Plantilla abstracta para static servlet de recursos que admite el almacenamiento en caché HTTP

Ajaxificando la forma

Dirígete a las siguientes respuestas sobre cómo cargar usando Ajax (y jQuery). ¡Tenga en cuenta que el código del servlet para recopilar los datos del formulario no necesita cambiarse 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 algo de JSON o XML o incluso texto sin formato dependiendo de lo que esté esperando el script responsable de la llamada Ajax).

  • ¿Cómo subir archivos al servidor usando JSP / Servlet y Ajax?
  • Enviar un archivo como multiparte a través de xmlHttpRequest
  • Carga de archivos HTML5 en Java Servlet

Espero que todo esto ayude 🙂

Si usa Spring MVC, así es como: (Dejo esto aquí en caso de que alguien lo encuentre útil).

Utilice un formulario con enctype attribute ajustado a “multipart/form-data“(Igual que la respuesta de BalusC)

En su controlador, asigne el parámetro de solicitud file para MultipartFile escriba de la siguiente manera:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public void handleUpload(@RequestParam("file") MultipartFile file) throws IOException 
    if (!file.isEmpty()) 
            byte[] bytes = file.getBytes(); // alternatively, file.getInputStream();
            // application logic
    

Puede obtener el nombre y el tamaño del archivo usando MultipartFile‘s getOriginalFilename() y getSize().

Probé esto con la versión Spring 4.1.1.RELEASE.

Sin componente ni biblioteca externa en Tomcat 6 o 7

Habilitando Subir en el web.xml expediente:

Manually Installing Php, Tomcat and Httpd Lounge


    jsp
    org.apache.jasper.servlet.JspServlet
    
      3145728
      5242880
    
    
        fork
        false
    
    
        xpoweredBy
        false
    
    3

COMO SE PUEDE VER:

    
      3145728
      5242880
    

Carga de archivos usando JSP. Archivos:

En el archivo html

En el archivo JSP o Servlet

    InputStream isFoto = request.getPart("fFoto").getInputStream();
    InputStream isResu = request.getPart("fResumen").getInputStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte buf[] = new byte[8192];
    int qt = 0;
    while ((qt = isResu.read(buf)) != -1) 
      baos.write(buf, 0, qt);
    
    String sResumen = baos.toString();

Edite su código según los requisitos del servlet, como Tamaño máximo de archivo, max-request-size y otras opciones que puede configurar …

Recuerda que puedes permitirte agregar una reseña si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4.5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *