lots of stuff and garbage code for automate to cleanup lots
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.geom.PageSize;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.EventType;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.data.IEventData;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.listener.IEventListener;
|
||||
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class CropController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CropController.class);
|
||||
|
||||
|
||||
@PostMapping(value = "/crop", consumes = "multipart/form-data")
|
||||
@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> cropPdf(
|
||||
@Parameter(description = "The input PDF file", required = true) @RequestParam("file") MultipartFile file,
|
||||
@Parameter(description = "The x-coordinate of the top-left corner of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("x") float x,
|
||||
@Parameter(description = "The y-coordinate of the top-left corner of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("y") float y,
|
||||
@Parameter(description = "The width of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("width") float width,
|
||||
@Parameter(description = "The height of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("height") float height) throws IOException {
|
||||
byte[] bytes = file.getBytes();
|
||||
System.out.println("x=" + x + ", " + "y=" + y + ", " + "width=" + width + ", " +"height=" + height );
|
||||
PdfReader reader = new PdfReader(new ByteArrayInputStream(bytes));
|
||||
PdfDocument pdfDoc = new PdfDocument(reader);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument outputPdf = new PdfDocument(writer);
|
||||
|
||||
int totalPages = pdfDoc.getNumberOfPages();
|
||||
|
||||
for (int i = 1; i <= totalPages; i++) {
|
||||
PdfPage page = outputPdf.addNewPage(new PageSize(width, height));
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page);
|
||||
|
||||
PdfFormXObject formXObject = pdfDoc.getPage(i).copyAsFormXObject(outputPdf);
|
||||
|
||||
// Save the graphics state, apply the transformations, add the object, and then
|
||||
// restore the graphics state
|
||||
pdfCanvas.saveState();
|
||||
pdfCanvas.rectangle(x, y, width, height);
|
||||
pdfCanvas.clip();
|
||||
pdfCanvas.addXObject(formXObject, -x, -y);
|
||||
pdfCanvas.restoreState();
|
||||
}
|
||||
|
||||
|
||||
outputPdf.close();
|
||||
byte[] pdfContent = baos.toByteArray();
|
||||
pdfDoc.close();
|
||||
return WebResponseUtils.bytesToWebResponse(pdfContent,
|
||||
file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_cropped.pdf");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -114,9 +114,9 @@ public class PageNumbersController {
|
||||
for (int i : pagesToNumberList) {
|
||||
PdfPage page = pdfDoc.getPage(i+1);
|
||||
Rectangle pageSize = page.getPageSize();
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
|
||||
|
||||
String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{p}", String.valueOf(pdfDoc.getNumberOfPages())) : String.valueOf(pageNumber);
|
||||
String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{total}", String.valueOf(pdfDoc.getNumberOfPages())) : String.valueOf(pageNumber);
|
||||
|
||||
PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);
|
||||
float textWidth = font.getWidth(text, fontSize);
|
||||
|
||||
@@ -20,7 +20,10 @@ import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -48,247 +51,328 @@ import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineOperation;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Pipeline", description = "Pipeline APIs")
|
||||
public class Controller {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Controller.class);
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
||||
final String jsonFileName = "pipelineCofig.json";
|
||||
|
||||
final String jsonFileName = "pipelineConfig.json";
|
||||
final String watchedFoldersDir = "watchedFolders/";
|
||||
@Scheduled(fixedRate = 5000)
|
||||
final String finishedFoldersDir = "finishedFolders/";
|
||||
|
||||
@Scheduled(fixedRate = 25000)
|
||||
public void scanFolders() {
|
||||
logger.info("Scanning folders...");
|
||||
Path watchedFolderPath = Paths.get(watchedFoldersDir);
|
||||
if (!Files.exists(watchedFolderPath)) {
|
||||
try {
|
||||
Files.createDirectories(watchedFolderPath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Files.exists(watchedFolderPath)) {
|
||||
try {
|
||||
Files.createDirectories(watchedFolderPath);
|
||||
logger.info("Created directory: {}", watchedFolderPath);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error creating directory: {}", watchedFolderPath, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
try (Stream<Path> paths = Files.walk(watchedFolderPath)) {
|
||||
paths.filter(Files::isDirectory).forEach(t -> {
|
||||
paths.filter(Files::isDirectory).forEach(t -> {
|
||||
try {
|
||||
if (!t.equals(watchedFolderPath) && !t.endsWith("processing")) {
|
||||
handleDirectory(t);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Error handling directory: {}", t, e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error walking through directory: {}", watchedFolderPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void handleDirectory(Path dir) throws Exception {
|
||||
Path jsonFile = dir.resolve(jsonFileName);
|
||||
Path processingDir = dir.resolve("processing"); // Directory to move files during processing
|
||||
if (!Files.exists(processingDir)) {
|
||||
Files.createDirectory(processingDir);
|
||||
}
|
||||
|
||||
if (Files.exists(jsonFile)) {
|
||||
// Read JSON file
|
||||
String jsonString;
|
||||
try {
|
||||
jsonString = new String(Files.readAllBytes(jsonFile));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Decode JSON to PipelineConfig
|
||||
PipelineConfig config;
|
||||
try {
|
||||
config = objectMapper.readValue(jsonString, PipelineConfig.class);
|
||||
// Assuming your PipelineConfig class has getters for all necessary fields, you can perform checks here
|
||||
if (config.getOperations() == null || config.getOutputDir() == null || config.getName() == null) {
|
||||
throw new IOException("Invalid JSON format");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// For each operation in the pipeline
|
||||
for (PipelineOperation operation : config.getOperations()) {
|
||||
// Collect all files based on fileInput
|
||||
File[] files;
|
||||
String fileInput = (String) operation.getParameters().get("fileInput");
|
||||
if ("automated".equals(fileInput)) {
|
||||
// If fileInput is "automated", process all files in the directory
|
||||
try (Stream<Path> paths = Files.list(dir)) {
|
||||
files = paths.filter(path -> !path.equals(jsonFile))
|
||||
.map(Path::toFile)
|
||||
.toArray(File[]::new);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// If fileInput contains a path, process only this file
|
||||
files = new File[]{new File(fileInput)};
|
||||
}
|
||||
|
||||
// Prepare the files for processing
|
||||
File[] filesToProcess = files.clone();
|
||||
for (File file : filesToProcess) {
|
||||
Files.move(file.toPath(), processingDir.resolve(file.getName()));
|
||||
}
|
||||
|
||||
// Process the files
|
||||
try {
|
||||
List<Resource> resources = handleFiles(filesToProcess, jsonString);
|
||||
|
||||
// Move resultant files and rename them as per config in JSON file
|
||||
for (Resource resource : resources) {
|
||||
String outputFileName = config.getOutputPattern().replace("{filename}", resource.getFile().getName());
|
||||
outputFileName = outputFileName.replace("{pipelineName}", config.getName());
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
outputFileName = outputFileName.replace("{date}", LocalDate.now().format(dateFormatter));
|
||||
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmss");
|
||||
outputFileName = outputFileName.replace("{time}", LocalTime.now().format(timeFormatter));
|
||||
// {filename} {folder} {date} {tmime} {pipeline}
|
||||
|
||||
Files.move(resource.getFile().toPath(), Paths.get(config.getOutputDir(), outputFileName));
|
||||
}
|
||||
|
||||
// If successful, delete the original files
|
||||
for (File file : filesToProcess) {
|
||||
Files.deleteIfExists(processingDir.resolve(file.getName()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// If an error occurs, move the original files back
|
||||
for (File file : filesToProcess) {
|
||||
Files.move(processingDir.resolve(file.getName()), file.toPath());
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
List<Resource> processFiles(List<Resource> outputFiles, String jsonString) throws Exception{
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
|
||||
boolean hasErrors = false;
|
||||
|
||||
for (JsonNode operationNode : pipelineNode) {
|
||||
String operation = operationNode.get("operation").asText();
|
||||
JsonNode parametersNode = operationNode.get("parameters");
|
||||
String inputFileExtension = "";
|
||||
if(operationNode.has("inputFileType")) {
|
||||
inputFileExtension = operationNode.get("inputFileType").asText();
|
||||
} else {
|
||||
inputFileExtension=".pdf";
|
||||
logger.info("Handling directory: {}", dir);
|
||||
Path jsonFile = dir.resolve(jsonFileName);
|
||||
Path processingDir = dir.resolve("processing"); // Directory to move files during processing
|
||||
if (!Files.exists(processingDir)) {
|
||||
Files.createDirectory(processingDir);
|
||||
logger.info("Created processing directory: {}", processingDir);
|
||||
}
|
||||
|
||||
List<Resource> newOutputFiles = new ArrayList<>();
|
||||
boolean hasInputFileType = false;
|
||||
|
||||
for (Resource file : outputFiles) {
|
||||
if (file.getFilename().endsWith(inputFileExtension)) {
|
||||
hasInputFileType = true;
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("fileInput", file);
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> parameters = parametersNode.fields();
|
||||
while (parameters.hasNext()) {
|
||||
Map.Entry<String, JsonNode> parameter = parameters.next();
|
||||
body.add(parameter.getKey(), parameter.getValue().asText());
|
||||
}
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
|
||||
HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
String url = "http://localhost:8080/" + operation;
|
||||
|
||||
ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.POST, entity, byte[].class);
|
||||
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)) {
|
||||
logPrintStream.println("Error: " + response.getBody());
|
||||
hasErrors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the response body is a zip file
|
||||
if (isZip(response.getBody())) {
|
||||
// Unzip the file and add all the files to the new output files
|
||||
newOutputFiles.addAll(unzip(response.getBody()));
|
||||
} else {
|
||||
Resource outputResource = new ByteArrayResource(response.getBody()) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getFilename(); // Preserving original filename
|
||||
}
|
||||
};
|
||||
newOutputFiles.add(outputResource);
|
||||
}
|
||||
if (Files.exists(jsonFile)) {
|
||||
// Read JSON file
|
||||
String jsonString;
|
||||
try {
|
||||
jsonString = new String(Files.readAllBytes(jsonFile));
|
||||
logger.info("Read JSON file: {}", jsonFile);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error reading JSON file: {}", jsonFile, e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasInputFileType) {
|
||||
logPrintStream.println("No files with extension " + inputFileExtension + " found for operation " + operation);
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
outputFiles = newOutputFiles;
|
||||
// Decode JSON to PipelineConfig
|
||||
PipelineConfig config;
|
||||
try {
|
||||
config = objectMapper.readValue(jsonString, PipelineConfig.class);
|
||||
// Assuming your PipelineConfig class has getters for all necessary fields, you
|
||||
// can perform checks here
|
||||
if (config.getOperations() == null || config.getOutputDir() == null || config.getName() == null) {
|
||||
throw new IOException("Invalid JSON format");
|
||||
}
|
||||
logger.info("Parsed PipelineConfig: {}", config);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error parsing PipelineConfig: {}", jsonString, e);
|
||||
return;
|
||||
}
|
||||
|
||||
// For each operation in the pipeline
|
||||
for (PipelineOperation operation : config.getOperations()) {
|
||||
logger.info("Processing operation: {}", operation.toString());
|
||||
// Collect all files based on fileInput
|
||||
File[] files;
|
||||
String fileInput = (String) operation.getParameters().get("fileInput");
|
||||
if ("automated".equals(fileInput)) {
|
||||
// If fileInput is "automated", process all files in the directory
|
||||
try (Stream<Path> paths = Files.list(dir)) {
|
||||
files = paths
|
||||
.filter(path -> !Files.isDirectory(path)) // exclude directories
|
||||
.filter(path -> !path.equals(jsonFile)) // exclude jsonFile
|
||||
.map(Path::toFile)
|
||||
.toArray(File[]::new);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// If fileInput contains a path, process only this file
|
||||
files = new File[] { new File(fileInput) };
|
||||
}
|
||||
|
||||
// Prepare the files for processing
|
||||
List<File> filesToProcess = new ArrayList<>();
|
||||
for (File file : files) {
|
||||
logger.info(file.getName());
|
||||
logger.info("{} to {}",file.toPath(), processingDir.resolve(file.getName()));
|
||||
Files.move(file.toPath(), processingDir.resolve(file.getName()));
|
||||
filesToProcess.add(processingDir.resolve(file.getName()).toFile());
|
||||
}
|
||||
|
||||
// Process the files
|
||||
try {
|
||||
List<Resource> resources = handleFiles(filesToProcess.toArray(new File[0]), jsonString);
|
||||
|
||||
if(resources == null) {
|
||||
return;
|
||||
}
|
||||
// Move resultant files and rename them as per config in JSON file
|
||||
for (Resource resource : resources) {
|
||||
String resourceName = resource.getFilename();
|
||||
String baseName = resourceName.substring(0, resourceName.lastIndexOf("."));
|
||||
String extension = resourceName.substring(resourceName.lastIndexOf(".")+1);
|
||||
|
||||
String outputFileName = config.getOutputPattern().replace("{filename}", baseName);
|
||||
|
||||
outputFileName = outputFileName.replace("{pipelineName}", config.getName());
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
outputFileName = outputFileName.replace("{date}", LocalDate.now().format(dateFormatter));
|
||||
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmss");
|
||||
outputFileName = outputFileName.replace("{time}", LocalTime.now().format(timeFormatter));
|
||||
|
||||
outputFileName += "." + extension;
|
||||
// {filename} {folder} {date} {tmime} {pipeline}
|
||||
String outputDir = config.getOutputDir();
|
||||
|
||||
// Check if the environment variable 'automatedOutputFolder' is set
|
||||
String outputFolder = System.getenv("automatedOutputFolder");
|
||||
|
||||
if (outputFolder == null || outputFolder.isEmpty()) {
|
||||
// If the environment variable is not set, use the default value
|
||||
outputFolder = finishedFoldersDir;
|
||||
}
|
||||
|
||||
// Replace the placeholders in the outputDir string
|
||||
outputDir = outputDir.replace("{outputFolder}", outputFolder);
|
||||
outputDir = outputDir.replace("{folderName}", dir.toString());
|
||||
outputDir = outputDir.replace("\\watchedFolders", "");
|
||||
Path outputPath;
|
||||
|
||||
if (Paths.get(outputDir).isAbsolute()) {
|
||||
// If it's an absolute path, use it directly
|
||||
outputPath = Paths.get(outputDir);
|
||||
} else {
|
||||
// If it's a relative path, make it relative to the current working directory
|
||||
outputPath = Paths.get(".", outputDir);
|
||||
}
|
||||
|
||||
|
||||
if (!Files.exists(outputPath)) {
|
||||
try {
|
||||
Files.createDirectories(outputPath);
|
||||
logger.info("Created directory: {}", outputPath);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error creating directory: {}", outputPath, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger.info("outputPath {}", outputPath);
|
||||
logger.info("outputPath.resolve(outputFileName).toString() {}", outputPath.resolve(outputFileName).toString());
|
||||
File newFile = new File(outputPath.resolve(outputFileName).toString());
|
||||
OutputStream os = new FileOutputStream(newFile);
|
||||
os.write(((ByteArrayResource)resource).getByteArray());
|
||||
os.close();
|
||||
logger.info("made {}", outputPath.resolve(outputFileName));
|
||||
}
|
||||
|
||||
// If successful, delete the original files
|
||||
for (File file : filesToProcess) {
|
||||
Files.deleteIfExists(processingDir.resolve(file.getName()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// If an error occurs, move the original files back
|
||||
for (File file : filesToProcess) {
|
||||
Files.move(processingDir.resolve(file.getName()), file.toPath());
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
logPrintStream.close();
|
||||
}
|
||||
|
||||
List<Resource> processFiles(List<Resource> outputFiles, String jsonString) throws Exception {
|
||||
|
||||
}
|
||||
return outputFiles;
|
||||
}
|
||||
|
||||
|
||||
List<Resource> handleFiles(File[] files, String jsonString) throws Exception{
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
|
||||
boolean hasErrors = false;
|
||||
List<Resource> outputFiles = new ArrayList<>();
|
||||
|
||||
for (File file : files) {
|
||||
Path path = Paths.get(file.getAbsolutePath());
|
||||
Resource fileResource = new ByteArrayResource(Files.readAllBytes(path)) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getName();
|
||||
}
|
||||
};
|
||||
outputFiles.add(fileResource);
|
||||
}
|
||||
return processFiles(outputFiles, jsonString);
|
||||
}
|
||||
|
||||
List<Resource> handleFiles(MultipartFile[] files, String jsonString) throws Exception{
|
||||
logger.info("Processing files... " + outputFiles);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
|
||||
boolean hasErrors = false;
|
||||
|
||||
for (JsonNode operationNode : pipelineNode) {
|
||||
String operation = operationNode.get("operation").asText();
|
||||
logger.info("Running operation: {}", operation);
|
||||
JsonNode parametersNode = operationNode.get("parameters");
|
||||
String inputFileExtension = "";
|
||||
if (operationNode.has("inputFileType")) {
|
||||
inputFileExtension = operationNode.get("inputFileType").asText();
|
||||
} else {
|
||||
inputFileExtension = ".pdf";
|
||||
}
|
||||
|
||||
List<Resource> newOutputFiles = new ArrayList<>();
|
||||
boolean hasInputFileType = false;
|
||||
|
||||
for (Resource file : outputFiles) {
|
||||
if (file.getFilename().endsWith(inputFileExtension)) {
|
||||
hasInputFileType = true;
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("fileInput", file);
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> parameters = parametersNode.fields();
|
||||
while (parameters.hasNext()) {
|
||||
Map.Entry<String, JsonNode> parameter = parameters.next();
|
||||
body.add(parameter.getKey(), parameter.getValue().asText());
|
||||
}
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
|
||||
HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
String url = "http://localhost:8080/" + operation;
|
||||
|
||||
ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.POST, entity, byte[].class);
|
||||
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)) {
|
||||
logPrintStream.println("Error: " + response.getBody());
|
||||
hasErrors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the response body is a zip file
|
||||
if (isZip(response.getBody())) {
|
||||
// Unzip the file and add all the files to the new output files
|
||||
newOutputFiles.addAll(unzip(response.getBody()));
|
||||
} else {
|
||||
Resource outputResource = new ByteArrayResource(response.getBody()) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getFilename(); // Preserving original filename
|
||||
}
|
||||
};
|
||||
newOutputFiles.add(outputResource);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasInputFileType) {
|
||||
logPrintStream.println(
|
||||
"No files with extension " + inputFileExtension + " found for operation " + operation);
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
outputFiles = newOutputFiles;
|
||||
}
|
||||
logPrintStream.close();
|
||||
|
||||
}
|
||||
if (hasErrors) {
|
||||
logger.error("Errors occurred during processing. Log: {}", logStream.toString());
|
||||
}
|
||||
return outputFiles;
|
||||
}
|
||||
|
||||
List<Resource> handleFiles(File[] files, String jsonString) throws Exception {
|
||||
if(files == null || files.length == 0) {
|
||||
logger.info("No files");
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.info("Handling files: {} files, with JSON string of length: {}", files.length, jsonString.length());
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
|
||||
boolean hasErrors = false;
|
||||
List<Resource> outputFiles = new ArrayList<>();
|
||||
|
||||
for (File file : files) {
|
||||
Path path = Paths.get(file.getAbsolutePath());
|
||||
System.out.println("Reading file: " + path); // debug statement
|
||||
|
||||
if (Files.exists(path)) {
|
||||
Resource fileResource = new ByteArrayResource(Files.readAllBytes(path)) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return file.getName();
|
||||
}
|
||||
};
|
||||
outputFiles.add(fileResource);
|
||||
} else {
|
||||
System.out.println("File not found: " + path); // debug statement
|
||||
}
|
||||
}
|
||||
logger.info("Files successfully loaded. Starting processing...");
|
||||
return processFiles(outputFiles, jsonString);
|
||||
}
|
||||
|
||||
List<Resource> handleFiles(MultipartFile[] files, String jsonString) throws Exception {
|
||||
if(files == null || files.length == 0) {
|
||||
logger.info("No files");
|
||||
return null;
|
||||
}
|
||||
logger.info("Handling files: {} files, with JSON string of length: {}", files.length, jsonString.length());
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(jsonString);
|
||||
|
||||
JsonNode pipelineNode = jsonNode.get("pipeline");
|
||||
|
||||
boolean hasErrors = false;
|
||||
List<Resource> outputFiles = new ArrayList<>();
|
||||
|
||||
@@ -301,53 +385,59 @@ List<Resource> handleFiles(File[] files, String jsonString) throws Exception{
|
||||
};
|
||||
outputFiles.add(fileResource);
|
||||
}
|
||||
logger.info("Files successfully loaded. Starting processing...");
|
||||
return processFiles(outputFiles, jsonString);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/handleData")
|
||||
public ResponseEntity<byte[]> handleData(@RequestPart("fileInput") MultipartFile[] files,
|
||||
@RequestParam("json") String jsonString) {
|
||||
logger.info("Received POST request to /handleData with {} files", files.length);
|
||||
try {
|
||||
|
||||
List<Resource> outputFiles = handleFiles(files, jsonString);
|
||||
List<Resource> outputFiles = handleFiles(files, jsonString);
|
||||
|
||||
if (outputFiles.size() == 1) {
|
||||
// If there is only one file, return it directly
|
||||
Resource singleFile = outputFiles.get(0);
|
||||
InputStream is = singleFile.getInputStream();
|
||||
byte[] bytes = new byte[(int)singleFile.contentLength()];
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(bytes, singleFile.getFilename(), MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
if (outputFiles != null && outputFiles.size() == 1) {
|
||||
// If there is only one file, return it directly
|
||||
Resource singleFile = outputFiles.get(0);
|
||||
InputStream is = singleFile.getInputStream();
|
||||
byte[] bytes = new byte[(int) singleFile.contentLength()];
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
|
||||
logger.info("Returning single file response...");
|
||||
return WebResponseUtils.bytesToWebResponse(bytes, singleFile.getFilename(),
|
||||
MediaType.APPLICATION_OCTET_STREAM);
|
||||
} else if (outputFiles == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a ByteArrayOutputStream to hold the zip
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zipOut = new ZipOutputStream(baos);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zipOut = new ZipOutputStream(baos);
|
||||
|
||||
// Loop through each file and add it to the zip
|
||||
for (Resource file : outputFiles) {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getFilename());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
// Loop through each file and add it to the zip
|
||||
for (Resource file : outputFiles) {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getFilename());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
|
||||
// Read the file into a byte array
|
||||
InputStream is = file.getInputStream();
|
||||
byte[] bytes = new byte[(int)file.contentLength()];
|
||||
is.read(bytes);
|
||||
// Read the file into a byte array
|
||||
InputStream is = file.getInputStream();
|
||||
byte[] bytes = new byte[(int) file.contentLength()];
|
||||
is.read(bytes);
|
||||
|
||||
// Write the bytes of the file to the zip
|
||||
zipOut.write(bytes, 0, bytes.length);
|
||||
zipOut.closeEntry();
|
||||
// Write the bytes of the file to the zip
|
||||
zipOut.write(bytes, 0, bytes.length);
|
||||
zipOut.closeEntry();
|
||||
|
||||
is.close();
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
||||
zipOut.close();
|
||||
|
||||
zipOut.close();
|
||||
|
||||
logger.info("Returning zipped file response...");
|
||||
return WebResponseUtils.boasToWebResponse(baos, "output.zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Error handling data: ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -362,6 +452,7 @@ List<Resource> handleFiles(File[] files, String jsonString) throws Exception{
|
||||
}
|
||||
|
||||
private List<Resource> unzip(byte[] data) throws IOException {
|
||||
logger.info("Unzipping data of length: {}", data.length);
|
||||
List<Resource> unzippedFiles = new ArrayList<>();
|
||||
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
@@ -387,6 +478,7 @@ List<Resource> handleFiles(File[] files, String jsonString) throws Exception{
|
||||
|
||||
// If the unzipped file is a zip file, unzip it
|
||||
if (isZip(baos.toByteArray())) {
|
||||
logger.info("File {} is a zip file. Unzipping...", filename);
|
||||
unzippedFiles.addAll(unzip(baos.toByteArray()));
|
||||
} else {
|
||||
unzippedFiles.add(fileResource);
|
||||
@@ -394,6 +486,8 @@ List<Resource> handleFiles(File[] files, String jsonString) throws Exception{
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Unzipping completed. {} files were unzipped.", unzippedFiles.size());
|
||||
return unzippedFiles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user