mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	page numbers and custom images
This commit is contained in:
		
							parent
							
								
									3c54429fe0
								
							
						
					
					
						commit
						f92482d89e
					
				
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -16,6 +16,12 @@ local.properties
 | 
			
		||||
.project
 | 
			
		||||
version.properties
 | 
			
		||||
 | 
			
		||||
#### Stirling-PDF Files ###
 | 
			
		||||
customFiles/
 | 
			
		||||
config/
 | 
			
		||||
watchedFolders/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Gradle
 | 
			
		||||
.gradle
 | 
			
		||||
.lock
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,12 @@ RUN apt-get update && \
 | 
			
		||||
        unoconv && \
 | 
			
		||||
    rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
#Install fonts
 | 
			
		||||
RUN mkdir /usr/share/fonts/opentype/noto/
 | 
			
		||||
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
 | 
			
		||||
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
 | 
			
		||||
RUN fc-cache -f -v
 | 
			
		||||
 | 
			
		||||
# Copy the application JAR file
 | 
			
		||||
COPY build/libs/*.jar app.jar
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -86,6 +86,8 @@ docker run -d \
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  Can also add these for customisation but are not required
 | 
			
		||||
  -v /location/of/extraConfigs:/configs \
 | 
			
		||||
  -v /location/of/customFiles:/customFiles \
 | 
			
		||||
  -e APP_HOME_NAME="Stirling PDF" \
 | 
			
		||||
  -e APP_HOME_DESCRIPTION="Your locally hosted one-stop-shop for all your PDF needs." \
 | 
			
		||||
  -e APP_NAVBAR_NAME="Stirling PDF" \
 | 
			
		||||
@ -104,6 +106,7 @@ services:
 | 
			
		||||
    volumes:
 | 
			
		||||
      - /location/of/trainingData:/usr/share/tesseract-ocr/4.00/tessdata #Required for extra OCR languages
 | 
			
		||||
#      - /location/of/extraConfigs:/configs
 | 
			
		||||
#      - /location/of/customFiles:/customFiles/
 | 
			
		||||
#    environment:
 | 
			
		||||
#      APP_LOCALE: en_GB
 | 
			
		||||
#      APP_HOME_NAME: Stirling PDF
 | 
			
		||||
@ -161,10 +164,11 @@ Using the same method you can also change
 | 
			
		||||
- Change root URI for Stirling-PDF ie change server.com/ to server.com/pdf-app by running APP_ROOT_PATH as pdf-app
 | 
			
		||||
- Disable and remove endpoints and functionality from Stirling-PDF. Currently the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma seperated lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image to pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Frooodle/Stirling-PDF/blob/main/groups.md) 
 | 
			
		||||
- Change the max file size allowed through the server with the environment variable MAX_FILE_SIZE. default  2000MB
 | 
			
		||||
- Customise static files such as app logo by placing files in the /customFiles/static/ directory. Example to customise app logo is placing a /customFiles/static/favicon.svg to override current SVG. This can be used to change any images/icons/css/fonts/js etc in Stirling-PDF
 | 
			
		||||
 | 
			
		||||
## API
 | 
			
		||||
For those wanting to use Stirling-PDFs backend API to link with their own custom scripting to edit PDFs you can view all existing API documentation
 | 
			
		||||
[here](https://app.swaggerhub.com/apis-docs/Frooodle/Stirling-PDF/) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation 
 | 
			
		||||
[here](https://app.swaggerhub.com/apis-docs/Frooodle/Stirling-PDF/) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation (Or by following the API button in your settings of Stirling-PDF)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## FAQ
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,10 @@
 | 
			
		||||
package stirling.software.SPDF;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.nio.file.Paths;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
			
		||||
@ -7,6 +12,7 @@ import org.springframework.core.env.Environment;
 | 
			
		||||
import org.springframework.scheduling.annotation.EnableScheduling;
 | 
			
		||||
 | 
			
		||||
import jakarta.annotation.PostConstruct;
 | 
			
		||||
import stirling.software.SPDF.utils.GeneralUtils;
 | 
			
		||||
 | 
			
		||||
@SpringBootApplication
 | 
			
		||||
//@EnableScheduling
 | 
			
		||||
@ -49,6 +55,10 @@ public class SPdfApplication {
 | 
			
		||||
			// TODO Auto-generated catch block
 | 
			
		||||
			e.printStackTrace();
 | 
			
		||||
		}
 | 
			
		||||
        
 | 
			
		||||
        GeneralUtils.createDir("customFiles/static/");
 | 
			
		||||
        GeneralUtils.createDir("customFiles/templates/");
 | 
			
		||||
        GeneralUtils.createDir("config");
 | 
			
		||||
        System.out.println("Stirling-PDF Started.");
 | 
			
		||||
        
 | 
			
		||||
        String port = System.getProperty("local.server.port");
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ package stirling.software.SPDF.config;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 | 
			
		||||
 | 
			
		||||
@Configuration
 | 
			
		||||
@ -15,4 +16,12 @@ public class WebMvcConfig implements WebMvcConfigurer {
 | 
			
		||||
    public void addInterceptors(InterceptorRegistry registry) {
 | 
			
		||||
        registry.addInterceptor(endpointInterceptor);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
 | 
			
		||||
        // Handler for external static resources
 | 
			
		||||
        registry.addResourceHandler("/**")
 | 
			
		||||
                .addResourceLocations("file:customFiles/static/", "classpath:/static/")
 | 
			
		||||
                .setCachePeriod(0); // Optional: disable caching
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,11 +52,11 @@ public class ScalePagesController {
 | 
			
		||||
	@Operation(summary = "Change the size of a PDF page/document", description = "This operation takes an input PDF file and the size to scale the pages to in the output PDF file. Input:PDF Output:PDF Type:SISO")
 | 
			
		||||
	public ResponseEntity<byte[]> scalePages(
 | 
			
		||||
			@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
 | 
			
		||||
			@Parameter(description = "The scale of pages in the output PDF. Acceptable values are A0-A10, B0-B9, LETTER, TABLOID, LEDGER, LEGAL, EXECUTIVE.", required = true, schema = @Schema(type = "String", allowableValues = {
 | 
			
		||||
			@Parameter(description = "The scale of pages in the output PDF. Acceptable values are A0-A10, B0-B9, LETTER, TABLOID, LEDGER, LEGAL, EXECUTIVE.", required = true, schema = @Schema(type = "string", allowableValues = {
 | 
			
		||||
					"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "B0", "B1", "B2", "B3", "B4",
 | 
			
		||||
					"B5", "B6", "B7", "B8", "B9", "LETTER", "TABLOID", "LEDGER", "LEGAL",
 | 
			
		||||
					"EXECUTIVE" })) @RequestParam("pageSize") String targetPageSize,
 | 
			
		||||
			@Parameter(description = "The scale of the content on the pages of the output PDF. Acceptable values are floats.", required = true, schema = @Schema(type = "float")) @RequestParam("scaleFactor") float scaleFactor)
 | 
			
		||||
			@Parameter(description = "The scale of the content on the pages of the output PDF. Acceptable values are floats.", required = true, schema = @Schema(type = "integer")) @RequestParam("scaleFactor") float scaleFactor)
 | 
			
		||||
			throws IOException {
 | 
			
		||||
 | 
			
		||||
		Map<String, PageSize> sizeMap = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
@ -221,6 +221,15 @@ public class CompressController {
 | 
			
		||||
        // Read the optimized PDF file
 | 
			
		||||
        byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
 | 
			
		||||
 | 
			
		||||
        // Check if optimized file is larger than the original
 | 
			
		||||
        if(pdfBytes.length > inputFileSize) {
 | 
			
		||||
            // Log the occurrence
 | 
			
		||||
            logger.warn("Optimized file is larger than the original. Returning the original file instead.");
 | 
			
		||||
 | 
			
		||||
            // Read the original file again
 | 
			
		||||
            pdfBytes = Files.readAllBytes(tempInputFile);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Clean up the temporary files
 | 
			
		||||
        Files.delete(tempInputFile);
 | 
			
		||||
        Files.delete(tempOutputFile);
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,176 @@
 | 
			
		||||
package stirling.software.SPDF.controller.api.other;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
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.PdfUtils;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.*;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.*;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.*;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
import org.springframework.http.*;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
import io.swagger.v3.oas.annotations.*;
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.*;
 | 
			
		||||
import io.swagger.v3.oas.annotations.parameters.*;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
 | 
			
		||||
import org.apache.tomcat.util.http.ResponseUtil;
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.URLEncoder;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
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 com.itextpdf.io.font.constants.StandardFonts;
 | 
			
		||||
import com.itextpdf.kernel.font.PdfFont;
 | 
			
		||||
import com.itextpdf.kernel.font.PdfFontFactory;
 | 
			
		||||
import com.itextpdf.kernel.geom.Rectangle;
 | 
			
		||||
import com.itextpdf.kernel.pdf.PdfReader;
 | 
			
		||||
import com.itextpdf.kernel.pdf.PdfWriter;
 | 
			
		||||
import com.itextpdf.kernel.pdf.PdfDocument;
 | 
			
		||||
import com.itextpdf.kernel.pdf.PdfPage;
 | 
			
		||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
 | 
			
		||||
import com.itextpdf.layout.Canvas;
 | 
			
		||||
import com.itextpdf.layout.element.Paragraph;
 | 
			
		||||
import com.itextpdf.layout.properties.TextAlignment;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@Tag(name = "Other", description = "Other APIs")
 | 
			
		||||
public class PageNumbersController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PageNumbersController.class);
 | 
			
		||||
 | 
			
		||||
    @PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data")
 | 
			
		||||
    @Operation(summary = "Add page numbers to a PDF document", description = "This operation takes an input PDF file and adds page numbers to it. Input:PDF Output:PDF Type:SISO")
 | 
			
		||||
    public ResponseEntity<byte[]> addPageNumbers(
 | 
			
		||||
        @Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
 | 
			
		||||
        @Parameter(description = "Custom margin: small/medium/large", required = true, schema = @Schema(type = "string", allowableValues = {"small", "medium", "large"})) @RequestParam("customMargin") String customMargin,
 | 
			
		||||
        @Parameter(description = "Position: 1 of 9 positions", required = true, schema = @Schema(type = "integer", minimum = "1", maximum = "9")) @RequestParam("position") int position,
 | 
			
		||||
        @Parameter(description = "Starting number", required = true, schema = @Schema(type = "integer", minimum = "1")) @RequestParam("startingNumber") int startingNumber,
 | 
			
		||||
        @Parameter(description = "Which pages to number, default all", required = false, schema = @Schema(type = "string")) @RequestParam(value = "pagesToNumber", required = false) String pagesToNumber,
 | 
			
		||||
        @Parameter(description = "Custom text: defaults to just number but can have things like \"Page {n} of {p}\"", required = false, schema = @Schema(type = "string")) @RequestParam(value = "customText", required = false) String customText)
 | 
			
		||||
        throws IOException {
 | 
			
		||||
 | 
			
		||||
        byte[] fileBytes = file.getBytes();
 | 
			
		||||
        ByteArrayInputStream bais = new ByteArrayInputStream(fileBytes);
 | 
			
		||||
 | 
			
		||||
        int pageNumber = startingNumber;
 | 
			
		||||
        float marginFactor;
 | 
			
		||||
        switch (customMargin.toLowerCase()) {
 | 
			
		||||
            case "small":
 | 
			
		||||
                marginFactor = 0.01f;
 | 
			
		||||
                break;
 | 
			
		||||
            case "medium":
 | 
			
		||||
                marginFactor = 0.025f;
 | 
			
		||||
                break;
 | 
			
		||||
            case "large":
 | 
			
		||||
                marginFactor = 0.05f;
 | 
			
		||||
                break;
 | 
			
		||||
            case "x-large":
 | 
			
		||||
                marginFactor = 0.1f;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                marginFactor = 0.01f;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        float fontSize = 12.0f;
 | 
			
		||||
 | 
			
		||||
        PdfReader reader = new PdfReader(bais);
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        PdfWriter writer = new PdfWriter(baos);
 | 
			
		||||
 | 
			
		||||
        PdfDocument pdfDoc = new PdfDocument(reader, writer);
 | 
			
		||||
 | 
			
		||||
        List<Integer> pagesToNumberList = GeneralUtils.parsePageList(pagesToNumber.split(","), pdfDoc.getNumberOfPages());
 | 
			
		||||
 | 
			
		||||
        for (int i : pagesToNumberList) {
 | 
			
		||||
            PdfPage page = pdfDoc.getPage(i+1);
 | 
			
		||||
            Rectangle pageSize = page.getPageSize();
 | 
			
		||||
            PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
 | 
			
		||||
 | 
			
		||||
            String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{p}", String.valueOf(pdfDoc.getNumberOfPages())) : String.valueOf(pageNumber);
 | 
			
		||||
 | 
			
		||||
            PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);
 | 
			
		||||
            float textWidth = font.getWidth(text, fontSize);
 | 
			
		||||
            float textHeight = font.getAscent(text, fontSize) - font.getDescent(text, fontSize);
 | 
			
		||||
 | 
			
		||||
            float x, y;
 | 
			
		||||
            TextAlignment alignment;
 | 
			
		||||
 | 
			
		||||
            int xGroup = (position - 1) % 3;
 | 
			
		||||
            int yGroup = 2 - (position - 1) / 3;
 | 
			
		||||
 | 
			
		||||
            switch (xGroup) {
 | 
			
		||||
                case 0:  // left
 | 
			
		||||
                    x = pageSize.getLeft() + marginFactor * pageSize.getWidth();
 | 
			
		||||
                    alignment = TextAlignment.LEFT;
 | 
			
		||||
                    break;
 | 
			
		||||
                case 1:  // center
 | 
			
		||||
                    x = pageSize.getLeft() + (pageSize.getWidth()) / 2;
 | 
			
		||||
                    alignment = TextAlignment.CENTER;
 | 
			
		||||
                    break;
 | 
			
		||||
                default: // right
 | 
			
		||||
                    x = pageSize.getRight() - marginFactor * pageSize.getWidth();
 | 
			
		||||
                    alignment = TextAlignment.RIGHT;
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (yGroup) {
 | 
			
		||||
            case 0:  // bottom
 | 
			
		||||
                y = pageSize.getBottom() +   marginFactor * pageSize.getHeight();
 | 
			
		||||
                break;
 | 
			
		||||
            case 1:  // middle
 | 
			
		||||
                y = pageSize.getBottom() + (pageSize.getHeight() ) / 2;
 | 
			
		||||
                break;
 | 
			
		||||
            default: // top
 | 
			
		||||
                y = pageSize.getTop() - marginFactor * pageSize.getHeight();
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            new Canvas(pdfCanvas, page.getPageSize())
 | 
			
		||||
                    .showTextAligned(new Paragraph(text).setFont(font).setFontSize(fontSize), x, y, alignment);
 | 
			
		||||
 | 
			
		||||
            pageNumber++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        pdfDoc.close();
 | 
			
		||||
        byte[] resultBytes = baos.toByteArray();
 | 
			
		||||
 | 
			
		||||
        return ResponseEntity.ok()
 | 
			
		||||
                .header("Content-Type", "application/pdf; charset=UTF-8")
 | 
			
		||||
                .header("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_numbersAdded.pdf", "UTF-8"))
 | 
			
		||||
                .body(resultBytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -32,6 +32,13 @@ public class OtherWebController {
 | 
			
		||||
        return modelAndView;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/add-page-numbers")
 | 
			
		||||
    @Hidden
 | 
			
		||||
    public String addPageNumbersForm(Model model) {
 | 
			
		||||
        model.addAttribute("currentPage", "add-page-numbers");
 | 
			
		||||
        return "other/add-page-numbers";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @GetMapping("/extract-images")
 | 
			
		||||
    @Hidden
 | 
			
		||||
    public String extractImagesForm(Model model) {
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,9 @@
 | 
			
		||||
package stirling.software.SPDF.utils;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.nio.file.Paths;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@ -88,4 +92,16 @@ public class GeneralUtils {
 | 
			
		||||
 | 
			
		||||
	    return newPageOrder;
 | 
			
		||||
	}
 | 
			
		||||
	public static boolean createDir(String path) {
 | 
			
		||||
		Path folder = Paths.get(path);
 | 
			
		||||
	    if (!Files.exists(folder)) {
 | 
			
		||||
	        try {
 | 
			
		||||
	            Files.createDirectories(folder);
 | 
			
		||||
	        } catch (IOException e) {
 | 
			
		||||
	            e.printStackTrace();
 | 
			
		||||
	            return false;
 | 
			
		||||
	        }
 | 
			
		||||
	    }
 | 
			
		||||
	    return true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ server.error.whitelabel.enabled=false
 | 
			
		||||
server.error.include-stacktrace=always
 | 
			
		||||
server.error.include-exception=true
 | 
			
		||||
server.error.include-message=always
 | 
			
		||||
 | 
			
		||||
\
 | 
			
		||||
server.servlet.session.tracking-modes=cookie
 | 
			
		||||
server.servlet.context-path=${APP_ROOT_PATH:/}
 | 
			
		||||
 | 
			
		||||
@ -26,3 +26,7 @@ spring.thymeleaf.encoding=UTF-8
 | 
			
		||||
 | 
			
		||||
server.connection-timeout=${CONNECTION_TIMEOUT:5m}
 | 
			
		||||
spring.mvc.async.request-timeout=${ASYNC_CONNECTION_TIMEOUT:300000}
 | 
			
		||||
 | 
			
		||||
spring.resources.static-locations=file:customFiles/static/
 | 
			
		||||
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
 | 
			
		||||
#spring.thymeleaf.cache=false
 | 
			
		||||
@ -132,8 +132,11 @@ home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
 | 
			
		||||
home.scalePages.title=Adjust page size/scale
 | 
			
		||||
home.scalePages.desc=Change the size/scale of a page and/or its contents.
 | 
			
		||||
 | 
			
		||||
home.pipeline.title=Pipeline
 | 
			
		||||
home.pipeline.desc=Pipeline desc.
 | 
			
		||||
home.pipeline.title=Pipeline (Advanced)
 | 
			
		||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
 | 
			
		||||
 | 
			
		||||
home.add-page-numbers.title=Add Page Numbers
 | 
			
		||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
 | 
			
		||||
 | 
			
		||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								src/main/resources/static/images/add-page-numbers.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/main/resources/static/images/add-page-numbers.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-123" viewBox="0 0 16 16">
 | 
			
		||||
  <path d="M2.873 11.297V4.142H1.699L0 5.379v1.137l1.64-1.18h.06v5.961h1.174Zm3.213-5.09v-.063c0-.618.44-1.169 1.196-1.169.676 0 1.174.44 1.174 1.106 0 .624-.42 1.101-.807 1.526L4.99 10.553v.744h4.78v-.99H6.643v-.069L8.41 8.252c.65-.724 1.237-1.332 1.237-2.27C9.646 4.849 8.723 4 7.308 4c-1.573 0-2.36 1.064-2.36 2.15v.057h1.138Zm6.559 1.883h.786c.823 0 1.374.481 1.379 1.179.01.707-.55 1.216-1.421 1.21-.77-.005-1.326-.419-1.379-.953h-1.095c.042 1.053.938 1.918 2.464 1.918 1.478 0 2.642-.839 2.62-2.144-.02-1.143-.922-1.651-1.551-1.714v-.063c.535-.09 1.347-.66 1.326-1.678-.026-1.053-.933-1.855-2.359-1.845-1.5.005-2.317.88-2.348 1.898h1.116c.032-.498.498-.944 1.206-.944.703 0 1.206.435 1.206 1.07.005.64-.504 1.106-1.2 1.106h-.75v.96Z"/>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 870 B  | 
@ -13,7 +13,7 @@
 | 
			
		||||
        <div class="container ">
 | 
			
		||||
 | 
			
		||||
            <a class="navbar-brand" href="#" th:href="@{/}" >
 | 
			
		||||
                <img th:if="${@navBarText} == 'Stirling PDF'" class="main-icon" src="favicon.svg" alt="icon">
 | 
			
		||||
                <img class="main-icon" src="favicon.svg" alt="icon">
 | 
			
		||||
                <span class="icon-text"  th:text="${@navBarText}"></span>
 | 
			
		||||
            </a>
 | 
			
		||||
 | 
			
		||||
@ -116,6 +116,7 @@
 | 
			
		||||
                            <div th:replace="~{fragments/navbarEntry :: navbarEntry ('repair', 'images/wrench.svg', 'home.repair.title', 'home.repair.desc')}"></div>
 | 
			
		||||
                            <div th:replace="~{fragments/navbarEntry :: navbarEntry ('remove-blanks', 'images/blank-file.svg', 'home.removeBlanks.title', 'home.removeBlanks.desc')}"></div>
 | 
			
		||||
                            <div th:replace="~{fragments/navbarEntry :: navbarEntry ('compare', 'images/scales.svg', 'home.compare.title', 'home.compare.desc')}"></div>
 | 
			
		||||
                            <div th:replace="~{fragments/navbarEntry :: navbarEntry ('compare', 'images/add-page-numbers.svg', 'home.add-page-numbers.title', 'home.add-page-numbers.desc')}"></div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </li>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@
 | 
			
		||||
            <!-- Features -->
 | 
			
		||||
            <div class="features-container container">
 | 
			
		||||
            
 | 
			
		||||
                <!--  <div th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', svgPath='images/pipeline.svg')}"></div>-->
 | 
			
		||||
                 <div th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', svgPath='images/pipeline.svg')}"></div>
 | 
			
		||||
                
 | 
			
		||||
                <div th:replace="~{fragments/card :: card(id='multi-tool', cardTitle=#{home.multiTool.title}, cardText=#{home.multiTool.desc}, cardLink='multi-tool', svgPath='images/tools.svg')}"></div>
 | 
			
		||||
                <div th:replace="~{fragments/card :: card(id='merge-pdfs', cardTitle=#{home.merge.title}, cardText=#{home.merge.desc}, cardLink='merge-pdfs', svgPath='images/union.svg')}"></div>
 | 
			
		||||
@ -67,6 +67,10 @@
 | 
			
		||||
                <div th:replace="~{fragments/card :: card(id='cert-sign', cardTitle=#{home.certSign.title}, cardText=#{home.certSign.desc}, cardLink='cert-sign', svgPath='images/award.svg')}"></div>
 | 
			
		||||
                <div th:replace="~{fragments/card :: card(id='multi-page-layout', cardTitle=#{home.pageLayout.title}, cardText=#{home.pageLayout.desc}, cardLink='multi-page-layout', svgPath='images/page-layout.svg')}"></div>
 | 
			
		||||
                <div th:replace="~{fragments/card :: card(id='scale-pages', cardTitle=#{home.scalePages.title}, cardText=#{home.scalePages.desc}, cardLink='scale-pages', svgPath='images/scale-pages.svg')}"></div>
 | 
			
		||||
                
 | 
			
		||||
                <div th:replace="~{fragments/card :: card(id='add-page-numbers', cardTitle=#{home.add-page-numbers.title}, cardText=#{home.add-page-numbers.desc}, cardLink='add-page-numbers', svgPath='images/add-page-numbers.svg')}"></div>
 | 
			
		||||
                
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										51
									
								
								src/main/resources/templates/other/add-page-numbers.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/main/resources/templates/other/add-page-numbers.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
 | 
			
		||||
 | 
			
		||||
<th:block th:insert="~{fragments/common :: head(title=#{autoCrop.title})}"></th:block>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
    <th:block th:insert="~{fragments/common :: game}"></th:block>
 | 
			
		||||
    <div id="page-container">
 | 
			
		||||
        <div id="content-wrap">
 | 
			
		||||
            <div th:insert="~{fragments/navbar.html :: navbar}"></div>
 | 
			
		||||
            <br> <br>
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <div class="row justify-content-center">
 | 
			
		||||
                    <div class="col-md-6">
 | 
			
		||||
                        <h2 th:text="#{addPageNumbers.header}"></h2>
 | 
			
		||||
                        <form method="post" enctype="multipart/form-data" th:action="@{add-page-numbers}">
 | 
			
		||||
						    <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
 | 
			
		||||
						    <br>
 | 
			
		||||
						    <label for="customMargin">Margin Size</label>
 | 
			
		||||
						    <select id="customMargin" name="customMargin" required>
 | 
			
		||||
						        <option value="" disabled selected>Select a margin size</option>
 | 
			
		||||
						        <option value="small">Small</option>
 | 
			
		||||
						        <option value="medium">Medium</option>
 | 
			
		||||
						        <option value="large">Large</option>
 | 
			
		||||
						    </select>
 | 
			
		||||
						    <br>
 | 
			
		||||
						    <label for="position">Position</label>
 | 
			
		||||
						    <input type="number" id="position" name="position" placeholder="Position: 1 of 9 positions" min="1" max="9" required/>
 | 
			
		||||
						    <br>
 | 
			
		||||
						    <label for="startingNumber">Starting Number</label>
 | 
			
		||||
						    <input type="number" id="startingNumber" name="startingNumber" placeholder="Starting number" min="1" required/>
 | 
			
		||||
						    <br>
 | 
			
		||||
						    <label for="pagesToNumber">Pages to Number</label>
 | 
			
		||||
						    <input type="text" id="pagesToNumber" name="pagesToNumber" placeholder="Which pages to number, default all"/>
 | 
			
		||||
						    <br>
 | 
			
		||||
						    <label for="customText">Custom Text</label>
 | 
			
		||||
						    <input type="text" id="customText" name="customText" placeholder="Custom text: defaults to just number but can have things like 'Page {n} of {p}'"/>
 | 
			
		||||
						    <br>
 | 
			
		||||
						    <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{addPageNumbers.submit}"></button>
 | 
			
		||||
						</form>
 | 
			
		||||
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
        <div th:insert="~{fragments/footer.html :: footer}"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user