From 57de3bea2f682ebad29b8df330019a949a41341d Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Fri, 19 Jan 2024 18:15:57 +0300 Subject: [PATCH] Correct download process --- .../redrise/marinesco/DownloadController.java | 88 ------------------- .../ThreadPoolTaskExecutorSettings.java | 2 +- .../ru/redrise/marinesco/library/Book.java | 7 +- .../marinesco/library/DownloadController.java | 55 ++++++++++++ .../marinesco/library/InpxScanner.java | 20 ++--- .../library/web/AuthorController.java | 2 - src/main/resources/application.yml | 4 +- src/main/resources/templates/author.html | 5 +- src/main/resources/templates/book.html | 2 +- src/main/resources/templates/search.html | 4 +- 10 files changed, 71 insertions(+), 118 deletions(-) delete mode 100644 src/main/java/ru/redrise/marinesco/DownloadController.java create mode 100644 src/main/java/ru/redrise/marinesco/library/DownloadController.java diff --git a/src/main/java/ru/redrise/marinesco/DownloadController.java b/src/main/java/ru/redrise/marinesco/DownloadController.java deleted file mode 100644 index f14b718..0000000 --- a/src/main/java/ru/redrise/marinesco/DownloadController.java +++ /dev/null @@ -1,88 +0,0 @@ -package ru.redrise.marinesco; - -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import org.springframework.core.io.FileSystemResource; -import org.springframework.http.ContentDisposition; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import jakarta.servlet.ServletOutputStream; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import ru.redrise.marinesco.settings.ApplicationSettings; - -@Slf4j -@Controller -@RequestMapping("/download") -public class DownloadController { - - private String filesLocation; - - public DownloadController(ApplicationSettings applicationSettings) { - this.filesLocation = applicationSettings.getFilesLocation(); - } - - @GetMapping(value = "/") - public void getMethodName(@RequestParam String container, - @RequestParam String file, - HttpServletResponse response) throws Exception { - - final FileSystemResource libraryLocation = new FileSystemResource(filesLocation + File.separator + container); - try (ZipInputStream zipInputStream = new ZipInputStream(libraryLocation.getInputStream())) { - ZipEntry zipEntry = zipInputStream.getNextEntry(); - - while (zipEntry != null) { - if (zipEntry.getName().contains(file)) { - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - response.setHeader(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment() - .filename(file+".fb2", StandardCharsets.UTF_8) //TODO: fix - .build() - .toString()); - ServletOutputStream outStream = response.getOutputStream(); - sendFile(zipEntry.getSize(), zipInputStream, outStream); - outStream.flush(); - outStream.close(); - return; - } - - zipEntry = zipInputStream.getNextEntry(); - } - } - throw new Exception("file not found " + - filesLocation + File.separator + container + " → " + file); - } - - private void sendFile(long fileSize, - ZipInputStream zipInputStream, - ServletOutputStream outStream) throws Exception { - - int blockSize = 0x200; - - if (fileSize < 0x200) - blockSize = (int) fileSize; - - byte[] block = new byte[blockSize]; - long i = 0; - - while (true) { - int actuallyRead = zipInputStream.read(block); - outStream.write(block, 0, actuallyRead); - i += actuallyRead; - if ((i + blockSize) > fileSize) { - blockSize = (int) (fileSize - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } - } - -} diff --git a/src/main/java/ru/redrise/marinesco/ThreadPoolTaskExecutorSettings.java b/src/main/java/ru/redrise/marinesco/ThreadPoolTaskExecutorSettings.java index eee0cf4..c7d12bf 100644 --- a/src/main/java/ru/redrise/marinesco/ThreadPoolTaskExecutorSettings.java +++ b/src/main/java/ru/redrise/marinesco/ThreadPoolTaskExecutorSettings.java @@ -8,7 +8,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @Configuration public class ThreadPoolTaskExecutorSettings { @Bean - public TaskExecutor configTaskExecutor(){ + public ThreadPoolTaskExecutor configTaskExecutor(){ final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(8); executor.setMaxPoolSize(16); diff --git a/src/main/java/ru/redrise/marinesco/library/Book.java b/src/main/java/ru/redrise/marinesco/library/Book.java index 2c5d7f0..909596e 100644 --- a/src/main/java/ru/redrise/marinesco/library/Book.java +++ b/src/main/java/ru/redrise/marinesco/library/Book.java @@ -8,16 +8,13 @@ import java.util.Set; import jakarta.persistence.Entity; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToMany; import jakarta.persistence.Transient; import lombok.AccessLevel; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import ru.redrise.marinesco.RainbowDump; -@Slf4j @Entity @Data @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) @@ -42,7 +39,7 @@ public class Book { private String fileExtension; // - concatenate to fsFileName private LocalDate addedDate; private String container; - + @Transient private int position = 0; @Transient @@ -59,7 +56,7 @@ public class Book { this.libraryId = libraryId; this.libraryVersion = libraryVersion; this.id = new String(line).hashCode(); - this.container = container + ".zip"; + this.container = container; this.authors = new ArrayList<>(); this.genres = new ArrayList<>(); parseAuthors(authorsCollection); diff --git a/src/main/java/ru/redrise/marinesco/library/DownloadController.java b/src/main/java/ru/redrise/marinesco/library/DownloadController.java new file mode 100644 index 0000000..85099c1 --- /dev/null +++ b/src/main/java/ru/redrise/marinesco/library/DownloadController.java @@ -0,0 +1,55 @@ +package ru.redrise.marinesco.library; + +import java.io.File; +import java.io.FileInputStream; +import java.nio.charset.StandardCharsets; + +import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.springframework.http.ContentDisposition; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.server.ResponseStatusException; + +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; +import ru.redrise.marinesco.settings.ApplicationSettings; + +@Controller +@RequestMapping("/download") +public class DownloadController { + + private final String filesLocation; + + public DownloadController(ApplicationSettings applicationSettings) { + this.filesLocation = applicationSettings.getFilesLocation(); + } + + @GetMapping(value = "/") + public void getMethodName(@RequestParam String container, + @RequestParam String file, + HttpServletResponse response) throws Exception { + try { + File bookFile = new File(filesLocation + File.separator + container + File.separator + file); + if (! bookFile.exists()) + throw new Exception("No file found :["); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, + ContentDisposition.attachment() + .filename(file + ".fb2", StandardCharsets.UTF_8) // TODO: fix + .build() + .toString()); + + try (ServletOutputStream outStream = response.getOutputStream(); + FileInputStream inputStream = new FileInputStream(bookFile)) { + IOUtils.copy(inputStream, outStream); + } + } catch (Exception e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Book not found [" + e.getMessage() + "]"); + } + } +} diff --git a/src/main/java/ru/redrise/marinesco/library/InpxScanner.java b/src/main/java/ru/redrise/marinesco/library/InpxScanner.java index 66764e0..6d05c28 100644 --- a/src/main/java/ru/redrise/marinesco/library/InpxScanner.java +++ b/src/main/java/ru/redrise/marinesco/library/InpxScanner.java @@ -3,9 +3,6 @@ package ru.redrise.marinesco.library; import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -17,7 +14,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.springframework.core.io.FileSystemResource; -import org.springframework.core.task.TaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; @@ -31,9 +28,8 @@ import ru.redrise.marinesco.settings.ApplicationSettings; @Component public class InpxScanner { private static volatile String lastRunErrors = ""; - private static LocalDateTime lastRunTime = LocalDateTime.of(1970, 01, 01, 0, 0, 0); - private TaskExecutor executor; + private ThreadPoolTaskExecutor executor; private LibraryMetadataRepository libraryMetadataRepository; private AuthorRepository authorRepository; private GenreRepository genreRepository; @@ -41,7 +37,7 @@ public class InpxScanner { private String filesLocation; - public InpxScanner(TaskExecutor executor, + public InpxScanner(ThreadPoolTaskExecutor executor, ApplicationSettings applicationSettings, AuthorRepository authorRepository, GenreRepository genreRepository, @@ -59,15 +55,9 @@ public class InpxScanner { * @return true if executed, false otherwise */ public boolean reScan() { - - LocalDateTime currentDateTime = LocalDateTime.now(); - - if (ChronoUnit.MINUTES.between(lastRunTime, currentDateTime) < 5) { - lastRunErrors = "Too frequent requests. Please whait 5 min. Last attmpt: " - + lastRunTime.format(DateTimeFormatter.ofPattern("DD.MM.YYYY HH:mm:ss")); + if (executor.getActiveCount() > 0) return false; - } - lastRunTime = currentDateTime; + lastRunErrors = ""; Thread scanThread = new Thread(() -> { diff --git a/src/main/java/ru/redrise/marinesco/library/web/AuthorController.java b/src/main/java/ru/redrise/marinesco/library/web/AuthorController.java index 67cb5eb..e99a9b5 100644 --- a/src/main/java/ru/redrise/marinesco/library/web/AuthorController.java +++ b/src/main/java/ru/redrise/marinesco/library/web/AuthorController.java @@ -1,12 +1,10 @@ package ru.redrise.marinesco.library.web; import java.util.Collections; -import java.util.Comparator; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.util.comparator.Comparators; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e69dd91..90eb1c7 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,8 +5,8 @@ spring: driver-class-name: org.h2.Driver generate-unique-name: false name: marinesco - url: jdbc:h2:mem:marinesco -# url: jdbc:h2:file:/tmp/h2 +# url: jdbc:h2:mem:marinesco +# url: jdbc:h2:file:/tmp/h22 username: sa password: jpa: diff --git a/src/main/resources/templates/author.html b/src/main/resources/templates/author.html index 447b100..9f8be64 100644 --- a/src/main/resources/templates/author.html +++ b/src/main/resources/templates/author.html @@ -16,7 +16,8 @@
-

+
+
@@ -28,7 +29,7 @@
-
diff --git a/src/main/resources/templates/book.html b/src/main/resources/templates/book.html index 7aa1415..8409f3f 100644 --- a/src/main/resources/templates/book.html +++ b/src/main/resources/templates/book.html @@ -23,7 +23,7 @@

-

diff --git a/src/main/resources/templates/search.html b/src/main/resources/templates/search.html index 4dea4d2..eebca0b 100644 --- a/src/main/resources/templates/search.html +++ b/src/main/resources/templates/search.html @@ -27,7 +27,7 @@ ,
- @@ -51,7 +51,7 @@ ,
-