I can´t open a .pdf in my browser by Java - java

I´m trying to open a pdf that I have created using iText library in my browser, but it fails.
This is the code I´m using to send to browser
File file = new File(path);
try{
//InputStream stream=blob.getBinaryStream();
InputStream streamEntrada = new FileInputStream(file);
//ServletOutputStream fileOutputStream = response.getOutputStream();
PrintWriter print = response.getWriter();
int ibit = 256;
while ((ibit) >= 0)
{
ibit = streamEntrada.read();
print.write(ibit);
}
response.setContentType("application/text");
response.setHeader("Content-Disposition", "attachment;filename="+name);
response.setHeader("Pragma", "cache");
response.setHeader("Cache-control", "private, max-age=0");
streamEntrada.close();
print.close();
return null;
}
catch(Exception e){
return null;
}
}
I tried with FileOutputStream but isn´t works. I´m desperate.
Thank you.
Now, I´m trying this way, but it doesn´t work:
public class MovilInfoAction extends DownloadAction{
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
//Here the creation of the PDF
//Storing data
PdfData dPdf = pdf.drawPDF(terminal);
String path = dPdf.getPath();//Path
String name = dPdf.getName()+".pdf";//Pdf´s name
String contentType = "application/pdf";//ContentType
response.setContentType(contentType);
response.setHeader("Content-Disposition","attachment; filename="+name);
response.setHeader("Cache-control", "private, max-age=0");
response.setHeader("Content-Disposition", "inline");
File file = new File(path);
byte[] pdfBytes = es.vodafone.framework.utils.Utils.getBytesFromFile(file);
return new ByteArrayStreamInfo(contentType, pdfBytes);
}
protected class ByteArrayStreamInfo implements StreamInfo {
protected String contentType;
protected byte[] bytes;
public ByteArrayStreamInfo(String contentType, byte[] bytes) {
this.contentType = contentType;
this.bytes = bytes;
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(bytes);
}
}
}

You specify the mimetype as application/text, when it should be application/pdf.

You should set the Header and ContentType before you write the data.
And set the Content Type to application/pdf.

change
response.setContentType("application/text");
to
response.setContentType("application/pdf");
and if you want your pdf to open in browser then make following change
response.setHeader("Content-Disposition", "inline");

Put the filename in double quote "
response.setHeader("Content-Disposition","attachment; filename=\"" + attachmentName + "\"");

Android Default Browser requires GET Request. It does not understand POST Request and hence cannot download the attachment. You can send a GET request as by sending GET request, it resolved my problem. Android browser generates a GET request on its own and sends it back to server. The response received after second request will be considered final by the browser even if GET request is sent on first time by the servlet.

Related

JSF command button can be clicked only once when calling servlet for file download

I have some command buttons in a jsf, one of which when clicked when create a file and download. In the action class that handle the jsf action , I create the url object that has the URL for calling the Servlet.
This all works , the file is downloaded one time when I click on the button , but the issue is , I cannot click on the button or any other command buttons on the page after this. Why is the request not complete? Please help.
<h:commandButton id="filedownloadbtn" action="#{fileDownloadInit.submit}" value = "thisform">
Action
try {
String baseURL = facesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
String url = baseURL + "/DataloadServlet";
facesContext.getCurrentInstance().getExternalContext().redirect(url);
return null;
} finally {
facesContext.responseComplete();
}'
DataloadServlet
public Object[] getFileNameAndData(HttpServletRequest request)
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
//does some processing...
return new Object[] {fileName, stream.toByteArray()};
}
FileDownloadservlet
public abstract class FileDownloadservlet extends javax.servlet.http.HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Object[] file = getFileNameAndData(request);
if (file != null)
{
String fileName = (String)file[0];
byte[] fileData = (byte[])file[1];
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName +"\"");
response.setHeader("Cache-Control", "no-cache, no-store"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
String contentType = "application/vnd.ms-excel";
response.setContentType(");
response.setContentLength(fileData.length);
try
{
OutputStream output = response.getOutputStream();
output.write(fileData);
output.flush();
output.close();
}
catch (IOException ex)
{
}
}
}

forwarding response to another action in struts and sending file in response

I'm forwarding an action to from doFilter method conditionally as the following code to another method :
public void dofilter(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request,
HttpServletResponse resp) {
String reportType = request.getParameter("reportType");
ActionForward actionForward = null;
try {
if (reportType.equals("completedChart")) {
actionForward = cmsGetCompeltedTasks(mapping, actionForm,request, resp);
} catch (Exception ex) {
ex.printStackTrace();
}
}
and my method that accepts the action and the response is that generates a jasper report file and sends it in the response :
public ActionForward cmsGetCompeltedTasks(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
JasperReport jasperReport = fileName = COMPLETED_TASK + format.format(new Date()).toString() + ".xlsx";
String filePath = servlet.getServletContext().getRealPath("") + fileName;
System.out.println(filePath);
JRXlsxExporter exporter = new JRXlsxExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, filePath);
exporter.exportReport();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.addHeader("Content-Disposition", "attachment; filename=" + fileName);
file = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(filePath);
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
responseOutputStream.flush();
fileInputStream.close();
responseOutputStream.close();
return mapping.findForward("cmsGetCompeltedTasks");
} catch (Exception e) {
e.printStackTrace();
} finally {
file.delete();
}
return null;
}
But no file is downloading and I get an exception:
java.lang.IllegalStateException: Cannot forward after response has been committed
You are writing to response in servlet and you should move it to JSP
just don't write to the response in the servlet. That's the responsibility of the JSP.
Move the lines using response to the JSP you redirect to
response.setContentType("application/vnd.openxmlformats- officedocument.spreadsheetml.sheet");
...
The problem was that I was firing Ajax request and I send the file to download in servlet response but the file to be download was handled by Ajax request in JavaScript on the success callback not the servlet response I handled the issue to send a direct URL to the file I want to download in the Ajax success call back and fire a new request to the that file specific URL.

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 :

How can I reuse JAX-RS Response into HttpServletResponse?

I have a Servlet which makes a request to my Rest API, and I want it to return the API Response content to the final user through the HttpServletResponse.
The content is actually a .xls file to download which I put in the Response with the StreamingOutput Object.
How can I do that ? I can't cast the Response into a HttpServletResponse
Rest API method :
#GET
#Produces( MediaType.APPLICATION_JSON )
#Path("bla")
public Response getTopicByName() {
final Workbook wb = new HSSFWorkbook();
StreamingOutput stream = new StreamingOutput() {
#Override
public void write(OutputStream output) throws IOException, WebApplicationException {
wb.write(output);
}
};
responseBuilder = responseBuilder.entity(stream);
responseBuilder = responseBuilder.status(Response.Status.OK);
responseBuilder = responseBuilder.header("Content-Disposition", "attachment; filename=" + device + ".xls");
return responseBuilder.build();
}
Servlet POST method :
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(url);
Response res = target. request().get();
if (res.getStatus() == 200) {
// how to put res stream into response stream ?
ServletOutputStream stream = response.getOutputStream();
}
client.close();
}
EDIT :
I tried TedTrippin method and after finding out the way to recover an InputStream from the Response, it worked well.
But I keep getting corrupted xls files. And it is quite annoying. I don't get those corrupted files when I make the request directly from the browser.
Got any clues where it comes from ?
POST method :
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(url + param + format);
Response res = target.request().get();
if (res.getStatus() == 200) {
response.setHeader("Content-Disposition", "attachment; filename=test.xls");
InputStream in = res.readEntity(InputStream.class);
ServletOutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
while (in.read(buffer) >= 0) {
out.write(buffer);
}
out.flush();
}
client.close();
}
Simplest way is to read the response stream and write it straight to the response output stream. Either use a library function from IOUtils or Guava or pure java...
try (InputStream in = ...;
OutputStream out = ...) {
byte[] buffer = new byte[1024];
while (in.read(buffer) >= 0)
out.write(buffer);
} catch (IOException ex) {
...
}
A nicer (depending on your view) way would be to read/save the response as a temporary file then you could return that or write it to the output stream.
Third approach would be to create a pipe, but I don't think that would be applicable here.

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