Add user profile picture storage service
parent
907e0327df
commit
b3144e5601
2
config
2
config
|
@ -1 +1 @@
|
|||
Subproject commit c02e79c9aad0a236f1549e849233f9b9193a025f
|
||||
Subproject commit ccf6fbb013c16dbda4ce5c76de706caed5ccde72
|
|
@ -1,7 +1,7 @@
|
|||
server.port = 9020
|
||||
spring.datasource.url = jdbc:mysql://localhost:3306/events
|
||||
spring.datasource.username = root
|
||||
spring.datasource.password = root
|
||||
spring.datasource.password = skorpion
|
||||
spring.jpa.generate-ddl=true
|
||||
user.password=dizda
|
||||
#
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
server.port=9010
|
||||
spring.datasource.url = jdbc:mysql://localhost:3306/teams
|
||||
spring.datasource.username = root
|
||||
spring.datasource.password = root
|
||||
spring.datasource.password = skorpion
|
||||
spring.jpa.generate-ddl=true
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package ba.steleks;
|
||||
|
||||
import ba.steleks.storage.StorageProperties;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(StorageProperties.class)
|
||||
public class SteleksServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package ba.steleks.controller;
|
||||
|
||||
import ba.steleks.model.User;
|
||||
import ba.steleks.repository.UsersJpaRepository;
|
||||
import ba.steleks.storage.StorageFileNotFoundException;
|
||||
import ba.steleks.storage.StorageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.webmvc.RepositoryRestController;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.core.io.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by admin on 02/04/2017.
|
||||
*/
|
||||
@RestController
|
||||
public class ProfilePictureController {
|
||||
|
||||
private final StorageService storageService;
|
||||
private final UsersJpaRepository repository;
|
||||
|
||||
@Autowired
|
||||
public ProfilePictureController(StorageService storageService, UsersJpaRepository repository) {
|
||||
this.storageService = storageService;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@GetMapping("/profilePictures/{filename:.+}")
|
||||
@ResponseBody
|
||||
public ResponseEntity<Resource> serveFile(@PathVariable String filename) {
|
||||
|
||||
Resource file = storageService.loadAsResource(filename);
|
||||
return ResponseEntity
|
||||
.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\""+file.getFilename()+"\"")
|
||||
.body(file);
|
||||
}
|
||||
|
||||
@PostMapping("/users/{userId}/profilePicture")
|
||||
public String handleFileUpload(@PathVariable Long userId, @RequestParam("file") MultipartFile file,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
|
||||
String[] names = file.getOriginalFilename().split("\\.");
|
||||
String dest = String.valueOf(userId + "_" + new Date().getTime()) + "." + names[names.length - 1];
|
||||
storageService.store(file, dest);
|
||||
redirectAttributes.addFlashAttribute("message",
|
||||
"You successfully uploaded " + file.getOriginalFilename() + "!");
|
||||
|
||||
User user = repository.findOne(userId);
|
||||
user.setProfilePictureUrl("http://localhost:8090/profilePictures/" + dest);
|
||||
repository.save(user);
|
||||
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
@ExceptionHandler(StorageFileNotFoundException.class)
|
||||
public ResponseEntity handleStorageFileNotFound(StorageFileNotFoundException exc) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ public class User {
|
|||
private String firstName;
|
||||
@NotNull
|
||||
private String lastName;
|
||||
@Column(updatable = false, insertable = false, columnDefinition="DATETIME default NOW()")
|
||||
@NotNull
|
||||
private Timestamp registrationDate;
|
||||
@NotNull
|
||||
private String email;
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package ba.steleks.storage;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Service
|
||||
public class FileSystemStorageService implements StorageService {
|
||||
|
||||
private final Path rootLocation;
|
||||
|
||||
@Autowired
|
||||
public FileSystemStorageService(StorageProperties properties) {
|
||||
this.rootLocation = Paths.get(properties.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(MultipartFile file, String dest) {
|
||||
try {
|
||||
if (file.isEmpty()) {
|
||||
throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
|
||||
}
|
||||
Files.copy(file.getInputStream(),
|
||||
this.rootLocation.resolve(dest));
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Path> loadAll() {
|
||||
try {
|
||||
return Files.walk(this.rootLocation, 1)
|
||||
.filter(path -> !path.equals(this.rootLocation))
|
||||
.map(path -> this.rootLocation.relativize(path));
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Failed to read stored files", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path load(String filename) {
|
||||
return rootLocation.resolve(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource loadAsResource(String filename) {
|
||||
try {
|
||||
Path file = load(filename);
|
||||
Resource resource = new UrlResource(file.toUri());
|
||||
if(resource.exists() || resource.isReadable()) {
|
||||
return resource;
|
||||
}
|
||||
else {
|
||||
throw new StorageFileNotFoundException("Could not read file: " + filename);
|
||||
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new StorageFileNotFoundException("Could not read file: " + filename, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
FileSystemUtils.deleteRecursively(rootLocation.toFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
Files.createDirectory(rootLocation);
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Could not initialize storage", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package ba.steleks.storage;
|
||||
|
||||
public class StorageException extends RuntimeException {
|
||||
|
||||
public StorageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public StorageException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ba.steleks.storage;
|
||||
|
||||
|
||||
public class StorageFileNotFoundException extends StorageException {
|
||||
|
||||
public StorageFileNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public StorageFileNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package ba.steleks.storage;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("storage")
|
||||
public class StorageProperties {
|
||||
|
||||
/**
|
||||
* Folder location for storing files
|
||||
*/
|
||||
private String location = "/Users/admin";
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ba.steleks.storage;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface StorageService {
|
||||
|
||||
void init();
|
||||
|
||||
void store(MultipartFile file, String dest);
|
||||
|
||||
Stream<Path> loadAll();
|
||||
|
||||
Path load(String filename);
|
||||
|
||||
Resource loadAsResource(String filename);
|
||||
|
||||
void deleteAll();
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
server.port = 8090
|
||||
spring.datasource.url = jdbc:mysql://localhost:3306/users
|
||||
spring.datasource.username = root
|
||||
spring.datasource.password = root
|
||||
spring.datasource.password = skorpion
|
||||
spring.jpa.generate-ddl=true
|
||||
|
||||
|
|
Reference in New Issue