How to display uploaded images in Spring MVC application
spring, spring-mvc
Solution
You have to save your files into an external folder.
For example I create a directory like `/home/webappFolder/` and inside it I create some other subdirectory. For example a repository directory where I store uploaded data.. a report subdirectory where I put my jasper report files.. etc
/home/webappFolder/repo
/home/webappFolder/report
/home/webappFolder/logs
As you can read in xml posted in your question:
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
in resources you serve up static resources.
Problem
I have Spring MVC app, and I want to place uploaded by user images into `resources/uploads` folder. Obviously, I want to serve them on my site. But when I tried to place `sample.png` into `resources` folder, just for testing purposes, webserver answered `"not found"`. I re-built project and picture became accessible. I deleted picture, it STILL was accessible. I re-built project and server answered what it should ("not found"). What it this strange behaviour? Are resources being built into final jar file? Does that mean, that all uploaded user pictures will not be accesible before re-building project? If so, I totally shouldn't place uploaded files into resources folder, so where should I place them? Why is that happening, and how should I serve these pictures? Thank you very much. Context.xml: ``` <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven> <message-converters> <beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <beans:property name="objectMapper" ref="customObjectMapper"/> </beans:bean> </message-converters> </annotation-driven> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" /> <!-- mustache.java --> <beans:bean id="viewResolver" class="org.springframework.web.servlet.view.mustache.MustacheViewResolver"> <beans:property name="cache" value="false" /> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".mustache" /> <beans:property name="templateLoader"> <beans:bean class="org.springframework.web.servlet.view.mustache.MustacheTemplateLoader" /> </beans:property> </beans:bean> <!-- Standard template engine --> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <!-- <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".jsp" /> </beans:bean> --> <context:component-scan base-package="com.me.myproject" /> <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with username root and blank password. Change below if it's not the case --> <beans:bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <beans:property name="driverClassName" value="com.mysql.jdbc.Driver"/> <beans:property name="url" value="jdbc:mysql://localhost:3306/myproject"/> <beans:property name="username" value="someone"/> <beans:property name="password" value="something"/> <beans:property name="validationQuery" value="SELECT 1"/> </beans:bean> <!-- FlyWay --> <beans:bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate"> <beans:property name="dataSource" ref="myDataSource"/> </beans:bean> <!-- Hibernate Session Factory --> <beans:bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" depends-on="flyway"> <beans:property name="dataSource" ref="myDataSource"/> <beans:property name="packagesToScan"> <beans:array> <beans:value>com.me.myproject</beans:value> </beans:array> </beans:property> <beans:property name="hibernateProperties"> <beans:value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.hbm2ddl.auto=validate </beans:value> </beans:property> </beans:bean> <!-- Hibernate Transaction Manager --> <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <beans:property name="sessionFactory" ref="mySessionFactory"/> </beans:bean> <!-- Activates annotation based transaction management --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans:beans> ``` Web.xml: ``` <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> ```