HttpServletResponse response: Ask user to download file instead of auto downloading - java

This is my download code. It just starts downloading the file without asking user. I've searched multiple forums and nothing seems to work. This is code is in a backing bean attached to a commandButton.
public void doDownloadFile() {
PrintWriter out = null;
try {
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition", "attachment;filename=test.csv");
out = response.getWriter();
CSVWriter writer = new CSVWriter(out);
List<String[]> stringList = new ArrayList<String[]>();
for (User user : userList) {
String[] string = {user.getEmail(), user.getName(), user.getPassword()};
stringList.add(string);
}
writer.writeAll(stringList);
out.flush();
} catch (IOException ex) {
Logger.getLogger(ViewLines.class.getName()).log(Level.SEVERE, null, ex);
} finally {
out.close();
}
}

This is most likely due to the fact your browser is configured to download files of these types without prompt. The code has nothing to do with it.

The behavior of what to do with a download is 100% local, meaning it's the browser, not you, that determines what to do in that case. Whether the user's browser just dumps the file in a download folder or allows him to save it to a particular spot is entirely up to the browser.
Not much to be done.

Related

Instead of displaying the message content, the browser automatically downloads the EML file

public void showMessageContent(#RequestParam("mailNum") Integer mailNum, HttpServletRequest req,HttpServletResponse response) throws MessagingException, IOException {
User user = (User) req.getSession().getAttribute("user");
Message message = MailUtils.getMail(user, mailNum);
ServletOutputStream out = response.getOutputStream();
try{
if(!message.isMimeType("multipart/mixed"))
{
response.setContentType("message/rfc822");
message.writeTo(out);
}
}catch (Exception e){
e.printStackTrace();
}
}
but the Browser can't display the e-mail content,it always automatically download EML files 。
How can I deal with it?
I'm not sure that an Internet browser is able to read EML files.
When you save a mail from Mozilla Thunderbird and you want to open it in Chrome, you'll have to save it as HTML file.
What browser are you trying to use ?

How to create a file with content and download it with THYMELEAF

I'm working on a spring boot project with thymeleaf and I need to create a file and put some lines on it then send it for the user to download it.
#PostMapping("/filegenerator")
public String createFile(#ModelAttribute("page") Page page, Model model) {
List<String> lines = new ArrayList<String>();
//Some code ..........
lines.forEach(l->{
System.out.println(l);
});
//Here I need to create a file with the List of lines
//And also put some code to download it
return "filegenerator";
}
So if you want to return a file, you probably want to stream it to limit the amount of memory used (or at least that was probably the reasoning of Spring Framework creators). In your case I understand that the file is fairly small and doesn't really have to be persisted anywhere. It's just a one time download based on the uploaded form, right?
so this approach worked on my PC:
#PostMapping("/filegenerator")
public void createFile(HttpServletResponse response) throws IOException {
List<String> lines = Arrays.asList("line1", "line2");
InputStream is = new ByteArrayInputStream(lines.stream().collect(Collectors.joining("\n")).getBytes());
IOUtils.copy(is, response.getOutputStream());
response.setContentType("application/sql");
response.setHeader("Content-Disposition", "attachment; filename=\"myquery.sql\"");
response.flushBuffer();
}
note the content-disposition header. It explicitly states that you don't want to display the file in the browser, but instead you want it to be downloaded as a file and myquery.sql is the name of that file that will be downloaded.
#Kamil janowski
This is how it looks like now
#PostMapping("/filegenerator")
public String createFile(#ModelAttribute("page") Page page, Model model,HttpServletResponse response) throws IOException{
List<String> lines = new ArrayList<String>();
if(page.getTables().get(0).getName()!="") {
List<String> output = so.createTable(page.getTables());
output.forEach(line -> lines.add(line));
}
if(page.getInserttables().get(0).getName()!="") {
List<String> output = so.insert(page.getInserttables());
output.forEach(line -> lines.add(line));
}
if(page.getUpdatetables().get(0).getName()!="") {
List<String> output = so.update(page.getUpdatetables());
output.forEach(line -> lines.add(line));
}
lines.forEach(l->{
System.out.println(l);
});
InputStream is = new ByteArrayInputStream(lines.stream().collect(Collectors.joining("\n")).getBytes());
IOUtils.copy(is, response.getOutputStream());
response.setContentType("application/sql");
response.setHeader("Content-Disposition", "attachment; filename=\"myquery.sql\"");
response.flushBuffer();
model.addAttribute("page", getPage());
return "filegenerator";
}

Send pdf jasper straight to the printer in web app

I need to send a pdf jasper directly to the printer, the current code PDF is delegated to the browser and therefore the user can print as many copies as desired. Must allow only print one copy, so I thought I'd send directly to printing.
I searched the forum but did not understand what would be the best solution to the issue.
Take a look at my code:
public class UtilRelatorios {
public static void imprimeRelatorio(String relatorioNome,
HashMap parametros) throws IOException, JRException {
FacesContext fc = FacesContext.getCurrentInstance();
ServletContext context = (ServletContext) fc.getExternalContext().getContext();
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
JasperPrint jasperPrint =
JasperFillManager.fillReport(
context.getRealPath("/relatorios")+ File.separator+relatorioNome+".jasper",
parametros);
//int finalPag = jasperPrint.getPages().size();
//System.out.println("page: "+finalPag);
//JasperPrintManager.printPage(jasperPrint,finalPag,false);
byte[] b = null;
//JasperPrintManager.printPage(jasperPrint, 0, false);
try {
b = JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
if (b != null && b.length > 0) {
// Envia o relatório em formato PDF para o browser
response.setContentType("application/pdf");
int codigo = (int) (Math.random()*1000);
response.setHeader("Content-disposition","inline);filename=relatorio_"+codigo+".pdf");
response.setContentLength(b.length);
ServletOutputStream ouputStream = response.getOutputStream();
ouputStream.write(b, 0, b.length);
ouputStream.flush();
ouputStream.close();
}
}
}
If as seems in question you like to send the report directly to user's printer via web application, browser.
This can not be done!, you can not control the web users printer directly from the browser (excluding the use of activeX or other home made plugins)
Probably this is luck since otherwise while navigating on internet you would have people printing alot of advertising on your printer....
If instead you like to send it to a printer attached to server, this can be done!
If its the server printer please let me know and I can pass you some code.
If the client & server PC are on the same network ie LAN, you can share the client's printer on the server, then send report to it just like you'd send to a locally installed printer.

Generating pdf with wkhtmltopdf and download the pdf

I am working in a old project.The project is in Spring MVC .In the project I have to generate a pdf file from a jsp page and store in a location and download that file. For that I am using wkhtmltopdf tool to convert the one specific jsp page into pdf format. Using wkhtmltopdf sometime works fine, it generate the pdf in specific location, but sometime it require more time. Also when I am trying to download the file from specific location , sometime it download a 0KB size file or sometime the downloaded file can't be open (with some size) but sometime download perfectly. If I check the file at define location, it exist and open normally.
Here is my code in controller class.
#RequestMapping(value="/dwn.htm",method=RequestMethod.GET)
public void dwAppFm(HttpSession session,HttpServletRequest request,HttpServletResponse response,#RequestParam String id) throws IOException,InterruptedException
{
final int BUFFER_SIZES=4096;
ServletContext context=request.getServletContext();
String savePath="/tmp/";//PDF file Generate Path
String fileName="PDFFileName"; //Pdf file name
FileInputStream inputStream=null;
BufferedInputStream bufferedInputStream=null;
OutputStream outputStream=null;
printApp(id,fileName);
Thread.sleep(1000);
printApp(id,fileName);
File download=new File(savePath+fileName+".pdf");
while(!download.canRead())
{
Thread.sleep(1000);
printApp(id,fileName);
download=new File(savePath+fileName+".pdf");
}
if(download.canRead()){//if the file can read
try{
Thread.sleep(1000);
inputStream=new FileInputStream(download);
bufferedInputStream=new BufferedInputStream(inputStream);
String mimeType = context.getMimeType(savePath+fileName+".pdf");
if (mimeType == null) {
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
response.setContentType(mimeType);
response.setContentLength((int)download.length());
String headerKey="Content-Disposition";
String headerValue=String.format("attachment;filename=\"%s\"", download.getName());
response.setHeader(headerKey, headerValue);
outputStream=response.getOutputStream();
byte[] buffer=new byte[BUFFER_SIZES];
int bytesRead=-1;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{
if(inputStream!=null)inputStream.close();
if(bufferedInputStream!=null)bufferedInputStream.close();
if(outputStream!=null)outputStream.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
public void printApp(String id,String fileName)
{
try{
String urlPath="http://localhost:8080/proj";
urlPath+="/genApp.htm?id="+id;//generate url to execute wkhtmltopdf
String wxpath="/home/exm/wkhtmltopdf";//the path where wkhtmltopdf located
String save="/tmp/"+fileName+".pdf";//File save Pathname
Process process=null;
process=Runtime.getRuntime().exec(wxpath+" "+urlPath+" "+save);
}catch(Exception e)
{}
}
#RequestMapping(value="/genApp.htm",method=RequestMethod.GET)
public String getApplicationPDF(HttpServletRequest request,HttpSession session,#RequestParam String id)
{
UDets uDets=uService.getAllById(Long.parseLong(id));//Methods to get details
request.setAttribute("uDets",uDets );
return "makeApp";//Name of the jsp page
}
In my code I have use Thread.sleep(1000) and printApp(id,fileName) method three times , since sometime wkhtmltopdf fail to generate pdf in certain time and then probability of downloading 0KB file is more. I haven't share the jsp page since the jsp page contain simple jsp page code of lots of line (the size of the generated pdf file is two page).
So the problem is what should I change in my code so that the pdf file generated and download without a failure also in heavy load in server.
If there is any best procedure or idea please share.
I don't like to use itext, since the jsp page contain complex design. Any advise is also appreciable and also thanks in advance.
I would say that your code is flawed not just a little but big time. You are checking if a file can be read, if not you start again a proces writing to the same file (at least twice). At some time you will endup with multiple processes trying to write to the same file, resulting in strange behavior.
I would refactor the printApp method to return the Process it created. Then call waitFor on that process. If it returns 0 and doesn't get interrupted it completed successfully and you should be able to download the file.
#RequestMapping(value="/dwn.htm",method=RequestMethod.GET)
public void dwAppFm(HttpSession session,HttpServletRequest request,HttpServletResponse response,#RequestParam String id) throws IOException,InterruptedException
{
String savePath="/tmp/";//PDF file Generate Path
String fileName="PDFFileName.pdf"; //Pdf file name
File download = new File(savePath, fileName);
try {
Process process = printApp(id, download.getPath());
int status = process.waitFor();
if (status == 0) {
response.setContentType("application/pdf");
response.setContentLength((int)download.length());
String headerKey="Content-Disposition";
String headerValue=String.format("attachment;filename=\"%s\"", download.getName());
StreamUtils.copy(new FileInputStream(download), response.getOutputStream())
} else {
// do something if it fails.
}
} catch (IOException ioe) {
// Do something to handle exception
} catch (InterruptedException ie) {
// Do something to handle exception
}
}
}
public Process printApp(String id, String pdf) throws IOException {
String urlPath="http://localhost:8080/proj";
urlPath+="/genApp.htm?id="+id;//generate url to execute wkhtmltopdf
String wxpath="/home/exm/wkhtmltopdf";//the path where wkhtmltopdf located
String command = wxpath+" "+urlPath+" "+pdf;
return Runtime.getRuntime().exec(command);
}
Something like the code above should to the trick.

RequestDispatcher.include is working only once

I am trying to output the rendering of a JSP page using RequestDispatcher.include() in the following method:
public static String readTemplate(HttpServletRequest request, HttpServletResponse response, String template) {
HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response) {
private final StringWriter sw = new StringWriter();
#Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(sw);
}
#Override
public String toString() {
return sw.toString();
}
};
String templateFile = "/templates/" + template + ".jsp";
logger.log(Level.INFO, "Reading template {0} ...", templateFile);
try {
request.getRequestDispatcher(templateFile).include(request, responseWrapper);
} catch (ServletException | IOException | IllegalStateException e) {
logger.log(Level.SEVERE, e.getMessage());
}
logger.log(Level.INFO, "Completed reading template {0}", templateFile);
// retrieve HTML from response
return responseWrapper.toString();
}
The method is part of a servlet I am running with Tomcat8. This works perfectly the first time, but hangs at the include call the second run (i.e. if I click refresh on the browser).
I have already verified the dispatcher is not null.
This is what I can see from the catalina.log (cleaned for your review)
First run:
26-Feb-2015 17:41:17.921 INFO [http-nio-8081-exec-2] ism.Reports.readTemplate Reading template /templates/INCIDENT_REPORT.jsp ...
26-Feb-2015 17:41:18.046 INFO [http-nio-8081-exec-2] ism.Reports.readTemplate Completed reading template /templates/INCIDENT_REPORT.jsp
Second run (response never returns, i.e. browser always loading page):
26-Feb-2015 17:41:26.327 INFO [http-nio-8081-exec-8] ism.Reports.readTemplate Reading template /templates/INCIDENT_REPORT.jsp ...
This does not change until I reboot Tomcat.
Can someone explain what am I doing wrong or at least how to debug this? Thanks!
EDIT 1: Forgot to say the method is static, but I also tried making it not static didn't make any difference
The code above is working, I realized where the issue was. The included JSP page was opening many MySQL connections but only one was closed. Hence the second request was waiting for the MYSQL resources to be freed before performing the task. I am very sorry I didn't notice this until now, and I didn't even mention MySQL connections in the first place. I guess not receiving replies here lead me to find the solution on the JSP file itself.

Categories