I have this MessageBody, to read PDF files. When performing a multipart-formdata in Insomnia passing two PDF files, I am only receiving one. The intention is to receive multiple files in the Multipart-formdata, and each file to be an index of the InputStream[] array, so that I can merge them all and thus return a single file. But I can't get more than 1 file (the first one from the request).
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Arrays;
@Provider
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public class MessagePdfBodyReader implements MessageBodyReader<InputStream[]> {
@Override
public boolean isReadable( Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType ) {
return mediaType.isCompatible( MediaType.valueOf( "application/pdf" ) );
}
@Override
public InputStream[] readFrom( Class<InputStream[]> aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> multivaluedMap, InputStream inputStream ) throws IOException, WebApplicationException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
byte[] pdfBytes = output.toByteArray();
return new InputStream[] { new ByteArrayInputStream(pdfBytes) };
}
}
Class to merge PDF's:
public class MergePdfService {
public byte[] executeService( InputStream[] pdffiles ) throws IOException, DocumentException {
return mergePdfs( pdffiles );
}
private byte[] mergePdfs(InputStream[] pdfFiles) throws IOException {
PDFMergerUtility merger = new PDFMergerUtility();
PDDocument merged = new PDDocument();
for (InputStream pdfFile : pdfFiles) {
File tempFile = File.createTempFile("temp", ".pdf");
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = pdfFile.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
try (PDDocument doc = Loader.loadPDF(tempFile)) {
merger.appendDocument(merged, doc);
} finally {
tempFile.delete();
System.out.println("Arquivo temporário deletado com sucesso!");
}
}
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
merged.save( baos );
System.out.println(pdfFiles.length);
return baos.toByteArray();
}
}
}
How i serialize: "@MultipartForm MergePdfModel form" I use this import: org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
The MergePdfModel class:
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.util.List;
public class MergePdfModel {
@FormParam("pdfFiles")
@PartType(MediaType.MULTIPART_FORM_DATA)
private InputStream[] pdfFiles;
@FormParam("pdfName")
@PartType(MediaType.TEXT_PLAIN)
private String pdfName;
public void setPdfName( String pdfName ) {
this.pdfName = pdfName;
}
public String getPdfName() {
return pdfName;
}
public InputStream[] getPdfFiles() {
return pdfFiles;
}
public void setPdfFiles( InputStream[] pdfFiles ) {
this.pdfFiles = pdfFiles;
}
}
This is my first post here,patience please.
I'm trying to receive multiple PDF files in the request using the MessageBodyReader, merge them all into a single file, and return it.
I managed to solve it, without needing the custom MessageBodyReader, using MultipartFormDataInput, this way it is possible to receive files of various extensions and manipulate them:
My "Controller":
public class MergePdfController {
@POST
@Path("execute/mergepdf")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response execute(MultipartFormDataInput input) {
try {
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
List<InputPart> inputParts = uploadForm.get("pdfFiles");
if (inputParts == null || inputParts.isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Nenhum arquivo PDF foi enviado")
.build();
}
List<InputStream> inputStreams = new ArrayList<>();
for (InputPart inputPart : inputParts) {
InputStream inputStream = inputPart.getBody(InputStream.class, null);
inputStreams.add(inputStream);
}
byte[] mergedPdfBytes = new MergePdfService().executeService(inputStreams);
return Response.ok(mergedPdfBytes, MediaType.APPLICATION_OCTET_STREAM_TYPE)
.header("Content-Disposition", "attachment; filename=merged.pdf")
.build();
my "model" to receive the MultipartFormDataInput:
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
public class MergePdfModel {
@FormParam("pdfFiles")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
private List<InputPart> pdfFiles;
public void setPdfFiles(List<InputPart> pdfFiles) {
this.pdfFiles = pdfFiles;
}
public List<InputPart> getPdfFiles() {
return pdfFiles;
}
}
My class to merge PDF's:
public class MergePdfService {
public byte[] executeService(List<InputStream> pdffiles) throws IOException, DocumentException {
System.out.println("EXECUTANDO O MERGE...");
return mergePdfs(pdffiles);
}
private byte[] mergePdfs(List<InputStream> pdfFiles) throws IOException {
PDFMergerUtility merger = new PDFMergerUtility();
PDDocument merged = new PDDocument();
for (InputStream pdfFile : pdfFiles) {
File tempFile = File.createTempFile("temp", ".pdf");
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = pdfFile.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
try (PDDocument doc = Loader.loadPDF(tempFile)) {
merger.appendDocument(merged, doc);
} finally {
tempFile.delete();
}
}
System.out.println("ARQUIVOS TEMPORÁRIOS CRIADOS E EXCLUIDOS");
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
merged.save(baos);
System.out.println("ARQUIVOS MERGEADOS!");
return baos.toByteArray();
}
}
}
Thanks for help :D