From 3582766baacb5468a3bc0b21f83f0484ebd947c6 Mon Sep 17 00:00:00 2001 From: esoe Date: Thu, 3 Oct 2024 17:59:59 +0300 Subject: [PATCH] =?UTF-8?q?xlsx-=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BE=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D0=BE=D0=B1=D0=BD=D0=BE=D1=81=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/api/ApiController.java | 23 ++ .../storage/models/xlsx/PageInfo.java | 7 - .../storage/models/xlsx/Xlsx.java | 108 +++++++++ .../storage/models/xlsx/XlsxDocument.java | 217 ------------------ .../models/xlsx/XlsxMultipartDocument.java | 104 --------- .../storage/models/xlsx/XlsxPage.java | 33 ++- .../storage/services/FileService.java | 2 +- .../storage/services/FileServiceImpl.java | 3 +- 8 files changed, 166 insertions(+), 331 deletions(-) delete mode 100644 storage/src/main/java/gsp/technologies/storage/models/xlsx/PageInfo.java create mode 100644 storage/src/main/java/gsp/technologies/storage/models/xlsx/Xlsx.java delete mode 100644 storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxDocument.java delete mode 100644 storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxMultipartDocument.java diff --git a/storage/src/main/java/gsp/technologies/storage/controllers/api/ApiController.java b/storage/src/main/java/gsp/technologies/storage/controllers/api/ApiController.java index 8fd5235..3ab5fb6 100644 --- a/storage/src/main/java/gsp/technologies/storage/controllers/api/ApiController.java +++ b/storage/src/main/java/gsp/technologies/storage/controllers/api/ApiController.java @@ -13,6 +13,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,6 +24,8 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import gsp.technologies.storage.models.FileMetadata; +import gsp.technologies.storage.models.xlsx.Xlsx; +import gsp.technologies.storage.models.xlsx.XlsxPage; import gsp.technologies.storage.services.FileService; @Controller @@ -165,6 +168,26 @@ public class ApiController { fs.deleteDirectory(name); } + @GetMapping("/files/xlsx") + public String getXlsxPage(Model model, + @RequestParam(name = "filename", required = true) String filename, + @RequestParam(name = "pageNumber", defaultValue = "0") String pageNumber, + @RequestParam(name = "pageSize", defaultValue = "10") String pageSize) { + LOG.info("GET /files/xlsx"); + LOG.info("filename: {}", filename); + LOG.info("pageNumber: {}", pageNumber); + LOG.info("pageSize: {}", pageSize); + Xlsx xlsx = new Xlsx(filename); + + XlsxPage page = xlsx.page(Integer.parseInt(pageSize), Integer.parseInt(pageNumber)); + + /** + * проверить обработку xlsx на больших данных + */ + model.addAttribute("page", page); + + return "view-xlsx"; + } } diff --git a/storage/src/main/java/gsp/technologies/storage/models/xlsx/PageInfo.java b/storage/src/main/java/gsp/technologies/storage/models/xlsx/PageInfo.java deleted file mode 100644 index 8b645a1..0000000 --- a/storage/src/main/java/gsp/technologies/storage/models/xlsx/PageInfo.java +++ /dev/null @@ -1,7 +0,0 @@ -package gsp.technologies.storage.models.xlsx; - -import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties.Pageable; - -public class PageInfo{ - -} diff --git a/storage/src/main/java/gsp/technologies/storage/models/xlsx/Xlsx.java b/storage/src/main/java/gsp/technologies/storage/models/xlsx/Xlsx.java new file mode 100644 index 0000000..7a24036 --- /dev/null +++ b/storage/src/main/java/gsp/technologies/storage/models/xlsx/Xlsx.java @@ -0,0 +1,108 @@ +package gsp.technologies.storage.models.xlsx; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gsp.technologies.storage.models.FileMetadata; + +public class Xlsx { + private static final Logger LOG = LoggerFactory.getLogger(Xlsx.class); + private FileMetadata metadata; + + public Xlsx(FileMetadata metadata) { + this.metadata = metadata; + } + + public Xlsx(String filename){ + this.metadata = new FileMetadata(filename); + } + + public XlsxPage page(int pageSize, int pageNumber) { + return XlsxPage.builder() + .pageSize(pageSize) + .pageNumber(pageNumber) + .metadata(metadata) + .content(this.content(pageSize, pageNumber)) + .totalLines(this.totalLines()) + .build(); + } + + Map> content(int pageSize, int pageNumber) { + Map> map = new HashMap<>(); + try (InputStream is = new FileInputStream(metadata.getPath())) { + XSSFWorkbook wb = new XSSFWorkbook(is); + XSSFSheet sheet = wb.getSheetAt(0); + int numberOfRows = sheet.getPhysicalNumberOfRows(); + + int startRow = pageNumber * pageSize; + int endRow = Math.min(startRow + pageSize, numberOfRows); + + for (int j = startRow; j < endRow; j++) { + Row row = sheet.getRow(j); + // do something with the row + List cells = new ArrayList<>(); + if (row == null) continue; //пустая строка + + Iterator cellIterator = row.cellIterator(); + while (cellIterator.hasNext()) { + Cell cell = cellIterator.next(); + cells.add(new XlsxCell(cell)); + } + + map.put(j, cells); + } + wb.close(); + } catch (IOException e) { + LOG.info("IOException: " + e.getMessage()); + } + return map; + } + + /** + * Возвращает общее количество строк в документе + * @return + */ + public Integer totalLines() { + int count = 0; + try (InputStream is = new FileInputStream(metadata.getPath())) { + XSSFWorkbook wb = new XSSFWorkbook(is); + XSSFSheet sheet = wb.getSheetAt(0); + // count = sheet.getLastRowNum(); + count = sheet.getPhysicalNumberOfRows(); + + + // Iterator rowIterator = sheet.rowIterator(); + // while (rowIterator.hasNext()) { + // Row row = rowIterator.next(); + // Iterator cellIterator = row.cellIterator(); + // while (cellIterator.hasNext()) { + // Cell cell = cellIterator.next(); + // // Use cell object to read data from the current cell + // } + // count++; + // } + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return count; + } + + + + +} diff --git a/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxDocument.java b/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxDocument.java deleted file mode 100644 index 49b0444..0000000 --- a/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxDocument.java +++ /dev/null @@ -1,217 +0,0 @@ -package gsp.technologies.storage.models.xlsx; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -// import org.apache.poi.util.IOUtils; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -// import lombok.AllArgsConstructor; -// import lombok.Data; -// import lombok.NoArgsConstructor; - -// @Data -// @AllArgsConstructor -// @NoArgsConstructor -public class XlsxDocument implements Serializable{ - private Map> data; - private Document document; - private List headers;//верхняя строка формы - - public XlsxDocument(Document document){ - this.document = document; - this.data = init(document); - this.headers = data.get(0); - } - - private Map> init(Document document) { - // IOUtils.setByteArrayMaxOverride(Integer.MAX_VALUE); - FileInputStream file; - Workbook workbook; - try { - file = new FileInputStream(new File(document.getPath())); - workbook = new XSSFWorkbook(file); - - Sheet sheet = workbook.getSheetAt(0); - data = new HashMap<>(); - Integer i = 0; - - //перебор строк - int rowStart = sheet.getFirstRowNum(); - int rowEnd = sheet.getLastRowNum(); - for (int rowNum = rowStart; rowNum < rowEnd; rowNum++){ - Row r = sheet.getRow(rowNum); - if (r != null) { - //перебор ячеек в строке - List xlsxCells = new ArrayList<>(); - XlsxCell xlsxCell = null; - int lastColumn = r.getLastCellNum(); - for (int cn = 0; cn < lastColumn; cn++){ - Cell cell = r.getCell(cn); - if (cell == null) { - //обработка нулевой ячейки - xlsxCell = new XlsxCell(""); - xlsxCell.setType("NULL"); - } else { - //обработка ячейки - switch (cell.getCellType()) { - case STRING: { - xlsxCell = new XlsxCell(cell.getStringCellValue() + ""); - xlsxCell.setType("STRING"); - } break; - case NUMERIC: { - if (DateUtil.isCellDateFormatted(cell)) { - xlsxCell = new XlsxCell(cell.getDateCellValue().getTime() + "" ); - xlsxCell.setType("DATE"); - } else { - xlsxCell = new XlsxCell(cell.getNumericCellValue() + ""); - xlsxCell.setType("NUMERIC"); - } - } break; - case BOOLEAN: { - xlsxCell = new XlsxCell(cell.getBooleanCellValue() + ""); - xlsxCell.setType("BOOLEAN"); - } break; - case FORMULA: { - xlsxCell = new XlsxCell(cell.getCellFormula() + ""); - xlsxCell = new XlsxCell("FORMULA"); - xlsxCell.setType("FORMULA"); - } break; - case BLANK: { - xlsxCell = new XlsxCell(""); - xlsxCell.setType("BLANK"); - } break; - case ERROR: { - xlsxCell = new XlsxCell(""); - xlsxCell.setType("ERROR"); - } break; - case _NONE: { - xlsxCell = new XlsxCell(""); - xlsxCell.setType("_NONE"); - } break; - } - } - xlsxCells.add(xlsxCell); - } - data.put(rowNum, xlsxCells); - } - } - }catch (IOException e) { - System.out.println("Не читается файл: " + e.getMessage()); - } - return data; - } - - /** - * @return the data - */ - public Map> getData() { - return data; - } - - /** - * @param data the data to set - */ - public void setData(Map> data) { - this.data = data; - } - - /** - * @return the document - */ - public Document getDocument() { - return document; - } - - /** - * @param document the document to set - */ - public void setDocument(Document document) { - this.document = document; - } - - /** - * @return the headers - */ - public List getHeaders() { - return headers; - } - - /** - * @param headers the headers to set - */ - public void setHeaders(List headers) { - this.headers = headers; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((data == null) ? 0 : data.hashCode()); - result = prime * result + ((document == null) ? 0 : document.hashCode()); - result = prime * result + ((headers == null) ? 0 : headers.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - XlsxDocument other = (XlsxDocument) obj; - if (data == null) { - if (other.data != null) - return false; - } else if (!data.equals(other.data)) - return false; - if (document == null) { - if (other.document != null) - return false; - } else if (!document.equals(other.document)) - return false; - if (headers == null) { - if (other.headers != null) - return false; - } else if (!headers.equals(other.headers)) - return false; - return true; - } - - @Override - public String toString() { - return "XlsxDocument [data=" + data + ", document=" + document + ", headers=" + headers + "]"; - } - - /** - * @param data - * @param document - * @param headers - */ - public XlsxDocument(Map> data, Document document, List headers) { - this.data = data; - this.document = document; - this.headers = headers; - } - - /** - * - */ - public XlsxDocument() { - } - -} diff --git a/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxMultipartDocument.java b/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxMultipartDocument.java deleted file mode 100644 index 5ad3f08..0000000 --- a/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxMultipartDocument.java +++ /dev/null @@ -1,104 +0,0 @@ -package gsp.technologies.storage.models.xlsx; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.springframework.stereotype.Service; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * Данные извлекаемые из файла порциями заданного размера - */ - -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Data -public class XlsxMultipartDocument { - private Document document; - private FileInputStream fis; - private Workbook workbook; - private Sheet sheet; - - public XlsxMultipartDocument(Document document){ - this.document = document; - try { - this.fis = new FileInputStream(new File(document.getPath())); - this.workbook = new XSSFWorkbook(fis); - this.sheet = workbook.getSheetAt(0); - } catch (IOException e) { - System.out.println("Не читается файл: " + e.getMessage()); - } - } - - /** - * Получение физического количества строк в документе, - * что бы это не значило - * @return - */ - public int getLineCount() { - return sheet.getPhysicalNumberOfRows(); - } - - public List line(int n) { - Row row = sheet.getRow(n); - List cells = new ArrayList<>(); - if (row == null) return cells; //пустая строка - - int i = 0; - int max = row.getLastCellNum(); - for (; i < max; i++) { - Cell cell = row.getCell(i); - cells.add(new XlsxCell(cell)); - } - return cells; - } - - public void close() { - try { - workbook.close(); - fis.close(); - } catch (IOException e) { - System.out.println("Не удалось закрыть потоки: " + e.getMessage()); - } - } - - public Map> lines(int from, int count) { - Map> lines = new HashMap<>(); - for (int i = from; i < from + count; i++) { - lines.put(i, line(i)); - } - return lines; - } - - public List column(int num) { - List cells = new ArrayList<>(); - for (int i = 0; i < getLineCount(); i++) { - cells.add(line(i).get(num)); - } - return cells; - } - - public List columnUnique(int num) { - List cells = new ArrayList<>(); - for (int i = 0; i < getLineCount(); i++) { - if (!cells.contains(line(i).get(num))) - cells.add(line(i).get(num)); - } - return cells; - } -} diff --git a/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxPage.java b/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxPage.java index 6deb52b..90ba941 100644 --- a/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxPage.java +++ b/storage/src/main/java/gsp/technologies/storage/models/xlsx/XlsxPage.java @@ -1,19 +1,50 @@ package gsp.technologies.storage.models.xlsx; +import java.util.HashMap; import java.util.List; import java.util.Map; import gsp.technologies.storage.models.FileMetadata; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; /** * Класс для хранения содержимого страницы, * сформированной из данных xlsx-файла */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder public class XlsxPage { private Map> content; private FileMetadata metadata; - private PageInfo info + //информация о странице + private int pageSize;//размер страницы, количество строк на странице + private int pageNumber;//номер текущей страницы + private int offset;//смещение начала извлечения данных из файла + private int headerLine;//номер строки в файле, содержащей заголовки + //сведения о положении страницы среди общей выборки страниц + private boolean last;//последняя страница + private boolean first;//первая страница + private boolean hasNext;//есть ли следующая страница + private boolean hasPrevious;//есть ли предыдущая страница + //информация о документе + private long totalLines;//общее количество строк + private int totalColumns;//общее количество столбцов + private int totalPages;//общее количество страниц + + public XlsxPage(FileMetadata metadata, int pageSize, int pageNumber, int offset, int headerLine) { + this.metadata = metadata; + this.pageSize = pageSize; + this.pageNumber = pageNumber; + this.headerLine = headerLine; + this.offset = offset; + // init(); + } } diff --git a/storage/src/main/java/gsp/technologies/storage/services/FileService.java b/storage/src/main/java/gsp/technologies/storage/services/FileService.java index 4e1d878..a2706a9 100644 --- a/storage/src/main/java/gsp/technologies/storage/services/FileService.java +++ b/storage/src/main/java/gsp/technologies/storage/services/FileService.java @@ -20,7 +20,7 @@ public interface FileService { String createFile(String path, String name, byte[] content); void createDirectory(String path, String name); void deleteDirectory(String name); - public Path root(); + Path root(); void init(); Resource loadAsResource(String filename); List store(MultipartFile[] files); diff --git a/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java b/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java index 11546e0..85d2fb9 100644 --- a/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java +++ b/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java @@ -20,14 +20,15 @@ import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import gsp.technologies.storage.config.StorageConfig; -import gsp.technologies.storage.controllers.api.ApiController; import gsp.technologies.storage.models.FileMetadata; +import gsp.technologies.storage.models.xlsx.XlsxPage; import jakarta.annotation.PostConstruct; @Service public class FileServiceImpl implements FileService { private static final Logger LOG = LoggerFactory.getLogger(FileServiceImpl.class); private final Path storageLocation; + public FileServiceImpl(StorageConfig config) { this.storageLocation = Paths.get(config.getLocation()) .toAbsolutePath().normalize();