diff --git a/data/db.mv.db b/data/db.mv.db index 231f77a..5e0da22 100644 Binary files a/data/db.mv.db and b/data/db.mv.db differ diff --git a/src/main/java/ru/ulstu/SeminarApplication.java b/src/main/java/ru/ulstu/SeminarApplication.java index 04b8e36..072438e 100644 --- a/src/main/java/ru/ulstu/SeminarApplication.java +++ b/src/main/java/ru/ulstu/SeminarApplication.java @@ -3,10 +3,12 @@ package ru.ulstu; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.event.EventListener; import ru.ulstu.user.UserService; @SpringBootApplication +@EnableConfigurationProperties public class SeminarApplication { private final UserService userService; diff --git a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java index f479e11..33b2cd9 100644 --- a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java +++ b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java @@ -45,7 +45,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { log.debug("Security enabled"); http.authorizeRequests() .antMatchers("/").permitAll() - .antMatchers("/login", "/index", "/news/**", "/meetings/**", "/h2-console/*", "/h2-console").permitAll() + .antMatchers("/login", "/index", "/news/**", "/meetings/**", "/files/**", "/h2-console/*", "/h2-console").permitAll() .antMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN) .anyRequest().authenticated() .and() diff --git a/src/main/java/ru/ulstu/files/FileSystemStorageService.java b/src/main/java/ru/ulstu/files/FileSystemStorageService.java new file mode 100644 index 0000000..805aa2f --- /dev/null +++ b/src/main/java/ru/ulstu/files/FileSystemStorageService.java @@ -0,0 +1,80 @@ +package ru.ulstu.files; + +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 { + public static final String UPLOAD_DIR = "upload"; + + private final Path rootLocation = Paths.get(UPLOAD_DIR); + + @Override + public void store(MultipartFile file) { + try { + if (file.isEmpty()) { + throw new StorageException("Failed to store empty file " + file.getOriginalFilename()); + } + Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename())); + } catch (IOException e) { + throw new StorageException("Failed to store file " + file.getOriginalFilename(), e); + } + } + + @Override + public Stream 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); + } + } +} diff --git a/src/main/java/ru/ulstu/service/FileUtil.java b/src/main/java/ru/ulstu/files/FileUtil.java similarity index 97% rename from src/main/java/ru/ulstu/service/FileUtil.java rename to src/main/java/ru/ulstu/files/FileUtil.java index af9fb4a..e2ccfc2 100644 --- a/src/main/java/ru/ulstu/service/FileUtil.java +++ b/src/main/java/ru/ulstu/files/FileUtil.java @@ -1,4 +1,4 @@ -package ru.ulstu.service; +package ru.ulstu.files; import org.springframework.web.multipart.MultipartFile; diff --git a/src/main/java/ru/ulstu/files/FilesController.java b/src/main/java/ru/ulstu/files/FilesController.java new file mode 100644 index 0000000..5df8814 --- /dev/null +++ b/src/main/java/ru/ulstu/files/FilesController.java @@ -0,0 +1,28 @@ +package ru.ulstu.files; + +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class FilesController { + private final StorageService storageService; + + public FilesController(StorageService storageService) { + this.storageService = storageService; + } + + @GetMapping("/files/{filename:.+}") + @ResponseBody + public ResponseEntity serveFile(@PathVariable String filename) { + Resource file = storageService.loadAsResource((filename == null || filename.equals("null") || filename.isEmpty()) + ? "logo.png" + : filename); + return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, + "filename=\"" + file.getFilename() + "\"").body(file); + } +} diff --git a/src/main/java/ru/ulstu/files/StorageException.java b/src/main/java/ru/ulstu/files/StorageException.java new file mode 100644 index 0000000..eb7da9f --- /dev/null +++ b/src/main/java/ru/ulstu/files/StorageException.java @@ -0,0 +1,12 @@ +package ru.ulstu.files; + +public class StorageException extends RuntimeException { + + public StorageException(String message) { + super(message); + } + + public StorageException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/ru/ulstu/files/StorageFileNotFoundException.java b/src/main/java/ru/ulstu/files/StorageFileNotFoundException.java new file mode 100644 index 0000000..085c94d --- /dev/null +++ b/src/main/java/ru/ulstu/files/StorageFileNotFoundException.java @@ -0,0 +1,12 @@ +package ru.ulstu.files; + +public class StorageFileNotFoundException extends StorageException { + + public StorageFileNotFoundException(String message) { + super(message); + } + + public StorageFileNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/ru/ulstu/files/StorageService.java b/src/main/java/ru/ulstu/files/StorageService.java new file mode 100644 index 0000000..48e3461 --- /dev/null +++ b/src/main/java/ru/ulstu/files/StorageService.java @@ -0,0 +1,23 @@ +package ru.ulstu.files; + +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); + + Stream loadAll(); + + Path load(String filename); + + Resource loadAsResource(String filename); + + void deleteAll(); + +} diff --git a/src/main/java/ru/ulstu/news/NewsService.java b/src/main/java/ru/ulstu/news/NewsService.java index 2c55c9c..eba9a17 100644 --- a/src/main/java/ru/ulstu/news/NewsService.java +++ b/src/main/java/ru/ulstu/news/NewsService.java @@ -3,7 +3,8 @@ package ru.ulstu.news; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import ru.ulstu.service.FileUtil; +import ru.ulstu.files.FileSystemStorageService; +import ru.ulstu.files.FileUtil; import javax.validation.constraints.NotNull; import java.io.IOException; @@ -37,9 +38,7 @@ public class NewsService { create(news); } - String uploadDir = "news-photos/"; - FileUtil.saveFile(uploadDir, fileName, news.getImageFile()); - + FileUtil.saveFile(FileSystemStorageService.UPLOAD_DIR, fileName, news.getImageFile()); } public News getById(@NotNull Integer id) { diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 81c63a7..4d04259 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -11,7 +11,7 @@
- +
diff --git a/src/main/resources/templates/news.html b/src/main/resources/templates/news.html index 3b444e5..edb3297 100644 --- a/src/main/resources/templates/news.html +++ b/src/main/resources/templates/news.html @@ -12,7 +12,7 @@
- +
diff --git a/src/main/resources/templates/viewNews.html b/src/main/resources/templates/viewNews.html index 06b6543..7dd007e 100644 --- a/src/main/resources/templates/viewNews.html +++ b/src/main/resources/templates/viewNews.html @@ -11,7 +11,7 @@
- +
diff --git a/upload/1647261445926 b/upload/1647261445926 new file mode 100644 index 0000000..39e27fa Binary files /dev/null and b/upload/1647261445926 differ diff --git a/upload/1647262081164 b/upload/1647262081164 new file mode 100644 index 0000000..9f581a0 Binary files /dev/null and b/upload/1647262081164 differ diff --git a/upload/1647262775259 b/upload/1647262775259 new file mode 100644 index 0000000..161b804 --- /dev/null +++ b/upload/1647262775259 @@ -0,0 +1,58 @@ + + +Created with Fabric.js 4.6.0 + + + + + + + + + + + + + + + diff --git a/upload/1647262911771 b/upload/1647262911771 new file mode 100644 index 0000000..e69de29 diff --git a/upload/1647262925015 b/upload/1647262925015 new file mode 100644 index 0000000..e69de29 diff --git a/upload/logo.png b/upload/logo.png new file mode 100644 index 0000000..366e9fd Binary files /dev/null and b/upload/logo.png differ