Reputation: 813
I'm trying to make a web app where you can upload an image which is saved in my file system and then served to the user at some address (kinda like imgur).
I've been having troubles with serving the images after they've been uploaded and saved in my system. It's been pointed out to me that the problem could be that I store the images as part of the source tree when I should be storing them in my projects target folder. Now, the reason that I store my images in project/src/main/resources/static/images in the first place is because I couldn't serve static content on my website from anywhere else.
I've been searching and reading up on this for a few days now and I haven't found any applicable solutions. The answers to these kind of problems usually involve files that my project doesn't have (like application-servlet.xml or web.xml) and that I've never used before (I'm very new to Spring, Spring-Boot and Java web development in general).
The base of my project was made by a tutor on github which I then cloned, including Application.java so the solutions I've seen using Spring Configuration don't fit either.
Here are (hopefully relevant)parts of my project:
This is my Application.java file. I've done nothing with it, it's exactly the same file as is in the original github that I cloned.
package project;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
/**
* The main class of the project.
* By running the main class of {@link Application} then you start the Spring Boot system
*/
@SpringBootApplication
public class Application extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder){
return applicationBuilder.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
Here's my application.properties. Here I just added the database stuff:
spring.view.prefix=/WEB-INF/jsp/
spring.view.suffix=.jsp
multipart.maxFileSize=-1
debug=true
spring.datasource.url=jdbc:postgresql://localhost:5432/finaltest
spring.datasource.username=myusername
spring.datasource.password=mypassword
Here's my pom.xml (the only xml file in my project). Here I just added database dependencies:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>HBV501G</groupId>
<artifactId>Spring_Web_MVC</artifactId>
<version>0.1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1200-jdbc41</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The rest of the project I made myself, starting with my UploadController. It just takes files, tags and types from a post request, writes the current file to a location in the file system under a randomly generated name and stores info about the file (type, tags, name and it's location in the filesystem) in a database:
package project.controller;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import project.service.MediaFile;
import project.service.MediaFileRepository;
@Controller
public class UploadController {
private final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private Random rnd = new Random();
private int randomLength = 8;
@Autowired
private MediaFileRepository repository;
@RequestMapping(value = "/uploadmedia", method = RequestMethod.GET)
public String uploadForm() {
return "upload";
}
@RequestMapping(value = "/uploadmedia", method = RequestMethod.POST)
public String uploadSubmit(@RequestParam(value="files[]") MultipartFile[] files,
@RequestParam("tags[]") String[] tags, @RequestParam("types[]") String[] types)
{
String[] tagsArray;
MultipartFile file;
String name;
String tag;
String path;
String type;
for (int i = 0; i < files.length; i++) {
file = files[i];
tagsArray = tags[i].split("\\s+");
type = types[i];
name = randomString(randomLength);
List<MediaFile> nameExists = repository.findByName(name);
while (nameExists.size() > 0) {
name = randomString(randomLength);
nameExists = repository.findByName(name);
}
path = "/Users/.../src/main/resources/static/img/" + name + type;
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(path)));
stream.write(bytes);
stream.close();
for (int j = 0; j < tagsArray.length; j++) {
tag = tagsArray[j].toLowerCase();
repository.save(new MediaFile(name, tag, path, type));
}
System.out.println("Success!");
} catch (Exception e) {
System.out.println("Failure... " + e.getMessage());
}
} else {
System.out.println("file is empty");
}
}
return "upload";
}
private String randomString( int len ){
StringBuilder sb = new StringBuilder( len );
for( int i = 0; i < len; i++ )
sb.append( AB.charAt( rnd.nextInt(AB.length()) ) );
return sb.toString();
}
}
...Next, here's my MediaController(The files being uploaded are some sort of media). It just checks if a url has a file with a corresponding name in the database and if it does, sends the path of the file to media.jsp.
package project.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import project.service.MediaFile;
import project.service.MediaFileRepository;
import java.util.List;
/**
* Created by johannesthorkell on 13.10.2015.
*/
@Controller
@RequestMapping("/media")
public class MediaController {
@Autowired
private MediaFileRepository repository;
@RequestMapping("/{media}")
public String newMedia(@PathVariable String media, Model model) {
List<MediaFile> nameExists = repository.findByName(media);
if (nameExists.size() > 0) {
MediaFile mediaFile = nameExists.get(0);
String name = mediaFile.getName();
String type = mediaFile.getType();
model.addAttribute("image", "/img/" + name + type);
return "media";
}
return "error";
}
}
...And finally, here's my media.jsp file. It just takes in the file location from my MediaController and puts it as the src attribute of an img element (the files I'm using to test this are image files).
<!DOCTYPE html>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home</title>
</head>
<h1>Media Upload</h1>
<img src="${image}">
<div id="links">
<a href="/uploadmedia">upload media</a>
<a href="/searchmedia">search media</a>
</div>
</body>
</html>
Upvotes: 4
Views: 7336
Reputation: 28519
You can create a @Configuration
bean, like
@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/**").addResourceLocations("file:///D:/your_image_location/");
}
}
be sure to place the bean in the same package where your Application
resides , or somewhere under it, so that it gets scanned automatically
Upvotes: 6