SpringBoot - Generate pdf using flying-saucer-pdf result into empty file - java

I'am tying to export a pdf file from html using fly-saucer, but the file is always empty and therefore can not be opened. Can anyone tell me what i am doing wrong.
Here is my current code:
String templateName = "test-pdf";
Context ctx = new Context();
String processedHtml = templateEngine.process(templateName, ctx);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(processedHtml);
renderer.layout();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
renderer.createPDF(baos, false);
// setting some response headers
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
// setting the content type
response.setContentType("application/pdf");
// the contentLength
response.setContentLength(baos.size());
OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();
System.out.println("PDF created successfully");

Related

Unable to download file in Spring MVC

My Controller to which the request is mapped-
I return the value from AJAX, to the controller-
$.ajax({
type: 'GET',
dataType: 'json',
contentType:"application/json",
url:"/Putty/downloadProcess/?param="+param
});
#RequestMapping(value = "/downloadProcess", method = RequestMethod.GET)
protected void download(#RequestParam("param") String value, HttpServletResponse response)
throws ServletException, IOException {
Properties prop = new Properties();
InputStream input = new FileInputStream("config.properties");;
prop.load(input);
System.out.println(value);
String path = prop.getProperty("path.MS1");
String filepath= path.concat(value);
System.out.println(filepath);
File downloadFile = new File(filepath);
FileInputStream inStream = new FileInputStream(downloadFile);
String mimeType = "application/octet-stream";
System.out.println("MIME type: " + mimeType);
// modifies response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile);
response.setHeader(headerKey, headerValue);
System.out.println(response);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inStream.close();
outStream.close();
This displays the filenames on my JSP
<c:forEach var="listValue" items="${files}">
<label onClick="download('${listValue}')">${listValue}</label>
<br>
</c:forEach>
The problem is that, I can see the MIME type on my console, along with the value returned by AJAX- The filename. But I do not get the Download dialog box, when I click on the file names, displayed on my JSP. Am I not handling the requests properly or I am missing something else.
Thanks!
Try it
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/octet-stream");
if (file.isFile())
{
response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFile.getName() + "\"");
try (FileInputStream inputStream = new FileInputStream(downloadFile ))
{
IOUtils.copy(inputStream, out);
}
}
The Open/Save dialogue appears by default so we can not force anything. It is a browser specific settings that you cant change on the client side.
For Mozilla Firefox example :

Set content type xml not working in servlet response

So I have a servlet which get the response from another servlet in order to do some formatting, generate a pdf from that and encode to base64:
//setting response to get xml
response.setContentType("text/xml;charset=iso-8859-1");
response.addHeader("Content-Type", "text/xml");
String pdf = "";
final StringWriter buffer = new StringWriter();
RequestDispatcher dispatcher = request.getRequestDispatcher(url); //another Servlet
//getting response from another servlet
if (dispatcher != null) {
dispatcher.include(request, new HttpServletResponseWrapper(response) {
private PrintWriter writer = new PrintWriter(buffer);
#Override
public PrintWriter getWriter() throws IOException {
return writer;
}
});
}
String jspResponse = buffer.toString();
/*
* do some stuff with jspResponse
* and putting into Document doc
*/
try {
//generating pdf content and encoding to base64
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
renderer.createPDF(baos);
byte[] base64 = Base64.encodeBase64(baos.toByteArray());
pdf = new String(base64);
}
catch (Throwable e) {
e.printStackTrace();
}
request.setAttribute("pdf", pdf);
dispatcher = request.getRequestDispatcher("/new.jsp");
dispatcher.include(request, response);
And the jsp:
<%# page contentType="text/xml" %><?xml version="1.0" encoding="iso-8859-1"?>
<MSG-S>
<PDF>
<E>
<!-- variable containing a string with 40K+ -->
<BASE64>${pdf}</BASE64>
</E>
</PDF>
</MSG-S>
The problem is that I'm still getting a content-type text/html:
I added only: response.setContentType("text/xml");, and I do get the contentType as XML.

Download pdf directly to browser when generated with itext

I am using itext to generate a pdf file from an html string. I get this error in my console:
Uncaught Error: Syntax error, unrecognized expression: %PDF-1.4
This is the code in my controller.
#RequestMapping(value = "/print",method = RequestMethod.POST)
public void print(String html,HttpServletResponse response,HttpServletRequest request) throws IOException,DocumentException {
try{
Document document = new Document();
// step 2
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter.getInstance(document, baos);
// step 3
document.open();
document.add(new Paragraph(html));
// step 5
document.close();
// setting some response headers
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
// setting the content type
response.setContentType("application/pdf");
// the contentlength
response.setContentLength(baos.size());
// write ByteArrayOutputStream to the ServletOutputStream
OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
}
catch(DocumentException e) {
throw new IOException(e.getMessage());
}
what you need to do is to stream the PDF file's bytes directly to the output stream and flush the response. In Spring you can do this like this:
#RequestMapping(value="/displayProcessFile/{processInstanceId}", method=RequestMethod.GET)
public ResponseEntity<byte[]> displayProcessFile(#PathVariable String processInstanceId) throws UnauthorizedUserAccessException{
Document processFile=null;
try {
processFile = documentService.retrieveProcessFile(Long.parseLong(processInstanceId));
} catch (ProcessFileNotFoundExpection e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
headers.add("content-disposition", "attachment;filename=" + processFile.getDocName());
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(processFile.getContent(), headers, HttpStatus.OK);
return response;
}

error displaying image in IE10

Server:
#RequestMapping(value = "/url/{size}/{id}", method = RequestMethod.GET)
public void getPortfolioFile(HttpServletResponse response,
#PathVariable("id") int id,
#PathVariable("size") int size)
{
File img = provider.getImage(id, size);
if (img != null) {
try {
FileCopyUtils.copy(FileCopyUtils.copyToByteArray(img), response.getOutputStream());
String mimeType = img.toURL().openConnection().getContentType();
response.setContentType(mimeType);
response.setContentLength((int) img.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + img.getName() + "\"");
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
html:
<img src="/url/2/${id}" onerror="$('#c').empty();" />
the problem is that IE10 don't display image. response body contains image, headers is 200 OK. whan can it be?
check in:
Chrome v43.0.2357.132
FireFox Developer Edition v40
IE v10
You need to set the headers before you write the content, else they are ignored.
String mimeType = img.toURL().openConnection().getContentType();
response.setContentType(mimeType);
response.setContentLength((int) img.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Content-Disposition", "attachment;
FileCopyUtils.copy(FileCopyUtils.copyToByteArray(img), response.getOutputStream());
EDIT:
you content-type "binary/octet-stream" does not make sense.
Here I would expect a "image/gif" or other appropriate content type.
I also would eliminate the content-disposition header.

iText + GAE : How create random URL?

sorry for my bad english. I'm using iText in GAE + GWT.. i made a example app and it works in google! but i have a problem whit the token of URL.
I have this RPC service which create the Document in a Array of Bytes and write this in the HttpSession, then in client onSuccess block i call a Servlet which send to the client the PDF . The String token = "258958395ai53" is a token where the client find the PDF but in this example y made the token static so i need to create the token randomly and make sure that the token don't repeat. Here is de code.
RPC Service:
public String getPdf() {
Document document = new Document();
String token = "258958395ai53";
// generate test PDF
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter.getInstance(document, baos);
document.open();
document.add(new Paragraph("¡HOLA PUTO MUNDO!"));
document.close();
byte[] pdf = baos.toByteArray();
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession();
session.setAttribute(token, pdf);
} catch (Exception e) {
System.out.println("ReportServlet::generatePDF::Exception "
+ e.getMessage());
}
return token;
}
Servlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// create output stream from byte array in session
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String token = request.getParameter("token");
byte[] pdf = (byte[]) request.getSession().getAttribute(token);
baos.write(pdf);
// setting some response headers
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0,pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/pdf");
// content length is needed for MSIE
response.setContentLength(baos.size());
// write ByteArrayOutputStream to ServletOutputStream
ServletOutputStream out = response.getOutputStream();
baos.writeTo(out);
out.flush();
out.close();
}
onSuccess:
public void onSuccess(String lista) {
String token = lista;
//Window.open("hello?token="+ token, "_blank","menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");
Dialog d = new Dialog();
d.setWidth(500);
d.setHeight(700);
d.setUrl(GWT.getModuleBaseURL()+"hello?token="+token);
d.show();
}
});
Any idea? .. Can view my example http://pdfprueba2.appspot.com/
You can use a random generator. There are more advanced random generators available such as SecureRandom (see here how it works). On top of this you can combine multiple unique elements to create an uber unique key. This article gives an overview of some of the methods used in creating such a thing.
Take in account that the more complexity you add, the more resources/time it will take.

Categories

Resources