2023-08-01 00:03:13 +01:00
package stirling.software.SPDF.controller.api ;
2023-09-02 00:05:50 +01:00
import java.awt.geom.AffineTransform ;
2023-08-01 00:03:13 +01:00
import java.io.ByteArrayOutputStream ;
2023-08-27 00:39:22 +01:00
import java.io.IOException ;
2023-08-01 00:03:13 +01:00
2023-09-03 01:24:02 +01:00
import org.apache.pdfbox.multipdf.LayerUtility ;
2023-09-02 00:05:50 +01:00
import org.apache.pdfbox.pdmodel.PDDocument ;
import org.apache.pdfbox.pdmodel.PDPage ;
2023-09-03 01:24:02 +01:00
import org.apache.pdfbox.pdmodel.PDPageContentStream ;
2023-09-02 00:05:50 +01:00
import org.apache.pdfbox.pdmodel.common.PDRectangle ;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject ;
2023-08-01 00:03:13 +01:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.http.ResponseEntity ;
2023-09-09 00:25:27 +01:00
import org.springframework.web.bind.annotation.ModelAttribute ;
2023-08-01 00:03:13 +01:00
import org.springframework.web.bind.annotation.PostMapping ;
2023-09-11 23:19:50 +01:00
import org.springframework.web.bind.annotation.RequestMapping ;
2023-08-01 00:03:13 +01:00
import org.springframework.web.bind.annotation.RestController ;
import io.swagger.v3.oas.annotations.Operation ;
import io.swagger.v3.oas.annotations.tags.Tag ;
2023-09-09 00:25:27 +01:00
import stirling.software.SPDF.model.api.PDFFile ;
2023-08-01 00:03:13 +01:00
import stirling.software.SPDF.utils.WebResponseUtils ;
@RestController
2023-09-11 23:19:50 +01:00
@RequestMapping ( " /api/v1/general " )
2023-08-01 00:03:13 +01:00
@Tag ( name = " General " , description = " General APIs " )
public class ToSinglePageController {
private static final Logger logger = LoggerFactory . getLogger ( ToSinglePageController . class ) ;
@PostMapping ( consumes = " multipart/form-data " , value = " /pdf-to-single-page " )
@Operation (
summary = " Convert a multi-page PDF into a single long page PDF " ,
description = " This endpoint converts a multi-page PDF document into a single paged PDF document. The width of the single page will be same as the input's width, but the height will be the sum of all the pages' heights. Input:PDF Output:PDF Type:SISO "
)
2023-09-09 00:25:27 +01:00
public ResponseEntity < byte [ ] > pdfToSinglePage ( @ModelAttribute PDFFile request ) throws IOException {
2023-08-01 00:03:13 +01:00
2023-09-02 19:12:08 +01:00
// Load the source document
2023-09-09 00:25:27 +01:00
PDDocument sourceDocument = PDDocument . load ( request . getFileInput ( ) . getInputStream ( ) ) ;
2023-09-02 19:12:08 +01:00
// Calculate total height and max width
float totalHeight = 0 ;
float maxWidth = 0 ;
for ( PDPage page : sourceDocument . getPages ( ) ) {
PDRectangle pageSize = page . getMediaBox ( ) ;
totalHeight + = pageSize . getHeight ( ) ;
maxWidth = Math . max ( maxWidth , pageSize . getWidth ( ) ) ;
}
// Create new document and page with calculated dimensions
PDDocument newDocument = new PDDocument ( ) ;
PDPage newPage = new PDPage ( new PDRectangle ( maxWidth , totalHeight ) ) ;
newDocument . addPage ( newPage ) ;
// Initialize the content stream of the new page
PDPageContentStream contentStream = new PDPageContentStream ( newDocument , newPage ) ;
contentStream . close ( ) ;
LayerUtility layerUtility = new LayerUtility ( newDocument ) ;
float yOffset = totalHeight ;
// For each page, copy its content to the new page at the correct offset
for ( PDPage page : sourceDocument . getPages ( ) ) {
PDFormXObject form = layerUtility . importPageAsForm ( sourceDocument , sourceDocument . getPages ( ) . indexOf ( page ) ) ;
AffineTransform af = AffineTransform . getTranslateInstance ( 0 , yOffset - page . getMediaBox ( ) . getHeight ( ) ) ;
layerUtility . wrapInSaveRestore ( newPage ) ;
String defaultLayerName = " Layer " + sourceDocument . getPages ( ) . indexOf ( page ) ;
layerUtility . appendFormAsLayer ( newPage , form , af , defaultLayerName ) ;
yOffset - = page . getMediaBox ( ) . getHeight ( ) ;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ;
newDocument . save ( baos ) ;
newDocument . close ( ) ;
sourceDocument . close ( ) ;
byte [ ] result = baos . toByteArray ( ) ;
2023-09-09 00:25:27 +01:00
return WebResponseUtils . bytesToWebResponse ( result , request . getFileInput ( ) . getOriginalFilename ( ) . replaceFirst ( " [.][^.]+$ " , " " ) + " _singlePage.pdf " ) ;
2023-09-02 19:12:08 +01:00
2023-08-01 00:03:13 +01:00
}
}