style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Subir archivo con Spring (upload file)

Hola a todos.

Estoy haciendo un pag web la cual debe de subir un archivo al servidor, esto con ayuda de spring. He visto muchos ejemplos en la web y la mayoria son iguales sin embargo cuando implemento el codigo no me obtiene el archivo que seleccione. Para que se den una idea esto es lo que llevo.

En el archivo JSP:

        <form action="fileUpload.htm" method="post" enctype="multipart/form-data">
                <br>Subir archivo <input type="file" name="fichero">
                <br><br/>
               
                <input type="submit" value="subir">
        </form>

En el applicationContext:

    <bean id="methodResolverUpLoad" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
                <property name="mappings">
                        <props>
                            <prop key="/upload/fileUpload.htm">fileUpload</prop>
                        </props>       
                </property>
     </bean>
   
    <bean id="miDiskFileItemFactory" class="org.apache.commons.fileupload.disk.DiskFileItemFactory"/>

    <bean name="miServletFileUpload" class="org.apache.commons.fileupload.servlet.ServletFileUpload">
        <constructor-arg index="0">
            <ref bean="miDiskFileItemFactory" />
        </constructor-arg>
        <property name="sizeMax" value="1048576" />
    </bean>
       
    <bean name="/upload/*" class="com.mx.develompment.controller.SubirArchivoController">
        <property name="servletFileUpload" ref="miServletFileUpload" />
        <property name="adminServicio" ref="adminServicio" />
    </bean>

En el controller:

                try {
                    if (servletFileUpload.isMultipartContent(request)) {
                       
                        List fileItemsList = servletFileUpload.parseRequest(request);

                        Iterator it = fileItemsList.iterator();

                        while (it.hasNext()) {
                            FileItem archivoActual = (FileItem) it.next();
                            String nombre = archivoActual.getName();
                            File archivoADisco = new File(nombre);

                            archivoADisco = new File("C:/archivos/" + archivoADisco.getName());

                            archivoActual.write(archivoADisco);
                        }
                    }

                } catch (FileUploadException ex) {
                    logger.error("No se ha podido guardar los archivos.");
                    ex.printStackTrace();
                } catch (Exception ex) {
                    logger.error("No se ha podido guardar los archivos.");
                    ex.printStackTrace();
                }

El error:

En si no es un error, sino que en la linea donde se obtiene la lista del request, es decir esta : List fileItemsList = servletFileUpload.parseRequest(request); me trae null, y por consiguiente no entra al ciclo wile, si alguno de ud pudiera tener una idea en donde esta el error, se lo agradeceria muchisimo.

Gracias

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

null, o lista vacía?

Si servletFileUpload.parseRequest(request) te da null, entonces se arroja NPE en la siguiente linea, porque invocas esa lista que es null... pero dices que no entra al while... que por cierto, si usas Java 5 ó 6, puedes usar for (FileItem archivoActual : fileItemsList) en vez del while y la primera linea dentro del while donde obtienes el siguiente item.

Corriste esto con un depurador o cómo sabes que no entra al while? Porque estás asumiento que sí entra al if, o sea que sí se detecta lo del multipart.

Y por último, el método error del logger, no acepta la excepción como parámetro? Y te la imprime junto con tu mensaje, para que no hagas lo de imprimir el stacktrace aparte...

Imagen de AlexSnake

Es cierto...

Tienes razon, hice una mal comentario, de hecho la lista viene vacia. Estoy depurando y he puesto un punto de ruptura después del try, luego inspecciono la variable fileItemsList y se muestra como [ ] . y Estoy trabajando con Java 6, pero aunque ponga el for que me indcas, sera el mismo resultado.

Imagen de ezamudio

while >> for

Sí, lo del for en vez de while era un simple comentario para compactar un poco el código. En la página donde está la forma multiparte, hay otras formas, o es la única? Tienes manera de pedir al request el valor del submit correspondiente a "fichero"?

Ah y viendo el código... yo no he usado ese de Spring pero he usado el commons-fileupload y lo que se hace es que con un método estático se pregunta si es multiparte el request y de ser así, se crea una instancia de una clase específica de la librería, algo así como MultipartRequest, a partir del request normal, y a esa instancia es a la que le pides los nombres y valores de los archivos. No será algo así lo que debes hacer? Y el método parseRequest te devuelve una lista vacía porque aunque el servletFileUpload sabe que el request es multiparte, no lo has convertido realmente a un request que sepa manejar datos multiparte... repito, no conozco el manejo de multipartes con Spring, pero pues tal vez sea algo similar al commons-fileupload.

Imagen de AlexSnake

commons-fileupload??

Bueno en la página donde está la forma multiparte, sí es la única que hay y para ser sincero no se de que maner apueda pedir al request el valor de "fichero", solo con un:

MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
CommonsMultipartFile fileRead = (CommonsMultipartFile) multipartRequest.getFile("fichero");

pero como tu mencionas, esa instancia se hace cuando se quiere leer un archivo.....

Me quedo un poco confunidido, puesto a que ocupo el jar commons-fileupload-1.2.1.jar, pero no se de que manera debo hacer una instancia de la clase que requiero, para hacer lo mismo que en la instancia anterior. También ya hice la validacion para saber si es multiparte:  if (servletFileUpload.isMultipartContent(request)) , pero me falta instanciar???

Imagen de AlexSnake

Instancia requerida

Oye ezamudio, encontre un ejemplo básico de como subir un archivo pero con un servlet. He comparado código y la diferencia que encontre es esta instancia:

            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload( factory );

De ahí en adelante el código es muy parecido. Pero que no se supone que cuando en el applicationContext.xml declaro el bean:  <bean id="miDiskFileItemFactory" class="org.apache.commons.fileupload.disk.DiskFileItemFactory"/> es para eviarme esa instancia??? Quiero suponer que ese bean inyecta el DiskFileItemFactory.

Imagen de ezamudio

DiskFileItemFactory

El DiskFileItemFactory lo dejaste con puros defaults... tal vez no puede crear los archivos por el directorio en donde los quiere guardar y por eso te da una lista vacía?

Imagen de ezamudio

ServletFileUpload

Y el ServletFileUpload se puede compartir? es thread-safe? No debes crear una instancia por cada petición o algo así?

Imagen de AlexSnake

Copy & page

Para ser sincero he tomado de base el ejemplo que se muestra en este blog (Espero que este permitido poner referncias de otros sitios, en caso contrario lo borro) y lo he seguido, pero no me funciona a mi, tal vez este haciendo algo mal :S

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">