In my project (Java SpringMVC3) I get an XLS file via HttpClient and I want that file to be downloaded like it's a real download. A popup window showing download dialog.
How can I do that?
Controller should copy the content of file to response object. Do not forget - controller function must return NULL. Below I show a working example from my application:
String filename = /* path to a file */
File file = new File(filename);
response.setContentType(new MimetypesFileTypeMap().getContentType(file));
response.setContentLength((int)file.length());
response.setHeader("content-disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));
InputStream is = new FileInputStream(file);
FileCopyUtils.copy(is, response.getOutputStream());
return null;
Basically you need to implement a Controller that takes care of the download and specify the response's header-mime type. then you invoke that Controller from the view.
Here is a short example how to specify a header-mime type
HTTP Header Mime Type in Websphere Application Server 7
Related
I created a pdf file based on the thymeleaf template i'm actually using the template resolver, flying saucer, to write the file on the output stream
but since i can't access the front in order to define the content of the recap which would be generated every now and then when the client needs to, i thought it would be better to generate the pdf file on the server side. So my question is:
Is there a way to get the output stream where my data is written and convert it in order to
write on the fly so it won't be created in the local storage
Here's a part of my business logic:
os = new FileOutputStream(pdf);
ITextRenderer renderer = new ITextRenderer();
renderer.layout();
renderer.createPDF(os);
i use this in my controller and i use attachement content attribut in the response entity
other then that i'm open to any suggestions
thanks in advance
I had a similar task some time ago for a simple Java EE + JSF project and here's how I did it:
byte[] asPdf = .... (your pdf data)
String filename = "demo.pdf";
HttpServletResponse response = Faces.getResponse(); // Using Omnifaces in this example, but that is irrelevant
// Details: https://stackoverflow.com/a/9394237/7598851
response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
response.setContentLength(asPdf.length);
response.setCharacterEncoding("UTF-8");
try (OutputStream output = response.getOutputStream()) {
output.write(asPdf);
} catch (IOException e) {
// ...
}
The complete project is here, the relevant code is in this file
I am using java and struts. I have a scenario where there is 'Download' link in the page. After clicking on this link the control goes to the Action class, where I have String content which I need to write to a .txt file and then download that txt file.
Eventually whenever we click on the download link, we should be able to download a txt file having content a particular string.
I used below piece of code,
FileOutputStream outputStream = new FileOutputStream(fileNameWithDirectory);
outputStream.write(fileContentString.getBytes());
outputStream.close();
ActionForward forward = new ActionForward("doc/" + filename);
forward.setName(filename);
forward.setRedirect(true);
return forward;
Also I tried with FileWriter in place of FileOutputStream like,
FileWriter fileWriter = new FileWriter(fileNameWithDirectory);
fileWriter.write(fileContentString);
fileWriter.flush();
fileWriter.close();
But always instead of downloading the txt file, the control opens a new window where the String content is written.
Please suggest me, how would I able to download that .txt file.
You should add Content-Disposition: attachment to say browser, that it should download the file, not to open it.
See more details here
Also Struts has DownloadAction, you may use it as well.
You don't need to write the file and then redirect to it. You can set a http response header called Content-Disposition and then print your data into the http response body.
use it like this
response.addHeader("Content-Disposition", "Content-Disposition: attachment; filename=\""+filename+"\"");
of course this depends on which technology stack you're using.
Convert your text file to stream. and set content type as you wanted to download.
response.setContentType("application/pdf");
try {
// get your file as InputStream
InputStream is = ...;
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, convertedTextFiletoStream);
} catch (IOException ex) {
log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
throw new RuntimeException("IOError writing file to output stream");
}
Just wondering is there any way to name the document after you specify the doc.name to a template
PDDocument doc = PDDocument.load(play.Play.application().resource("/templates/" + FileName));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
doc.save(byteArrayOutputStream);
doc.close();
therefore, when you download PDFBOX rendered file, the name of the pdf file can not be specified. is there any other way to do it?
I am not familiar with Play framework.
If you want to enable users to download the file and provide it a filename, then you need to set the HTTP header
Content-Disposition: attachment; filename=myfile.pdf
When the browser sees this header, the user will get a dialog box to save the file and will suggest the name to be myfile.pdf.
here i'm trying to read pdf file from server using java servlet. the below code i'm getting file path if file exists and then try to read file but,file does not open ?
String filePath = dirName;
String fileName = si + "_" + dnldFilename;
FileInputStream fileToDownload = new FileInputStream(filePath.concat(fileName);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setContentLength(fileToDownload.available());
int c;
while ((c = fileToDownload.read()) != -1) {
response.getOutputStream().write(c);
}
response.getOutputStream().flush();
response.getOutputStream().close();
fileToDownload.close();
The bug is here:
response.setContentLength(fileToDownload.available());
The InputStream#available() doesn't do what you (and the average Java starter) think. It doesn't return the total content length which is what the response header represents. It returns the amount of bytes available for reading without blocking all other threads (i.e. bytes which are currently already put in hardware buffer). If this is lower than the actual file size, then the client may simply stop reading the remainder of the response. In other words, the client got only a part of the PDF file, because you told the client that the desired part is of exactly the given length.
You need to construct a normal java.io.File and get the file size via File#length().
Here's a complete rewrite, reducing further legacy Java IO boilerplate too. This assumes you're on at least Java 7 (as Java 6 is EOL since 2013, no one would expect you're 2 years after date still at Java 6 anyway):
File file = new File(filePath, fileName);
response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
That's it. Do note that the above code snippet is this way reusable for all other kinds of files too. You can manage unknown content types via <mime-mapping> entries in web.xml.
Also note that I'm converting the content length to string as the setContentLength() takes only an int and File#length() returns long, which would fail if the file is larger than 2GB. In case you're on Servlet 3.1 (Tomcat 8, etc) already, make use of new setContentLengthLong() method.
response.setContentLengthLong(file.length());
See also:
Simplest way to serve static data from outside the application server in a Java web application
Abstract template for static resource servlet
I've a Servlet that makes and returns a zip file
Something like this
response.setHeader("Pragma","Public");
response.setHeader("Cache-Control","must-revalidate,post-check=0,pre-check=0");
response.setContentType("application/octet-stream");
response.setHeader("Expires", "0");
response.setHeader("Content-Transfer-Encoding", "binary");
if(file.getName().contains("–")){
response.setHeader("Content-Disposition", "inline; filename=\"file.zip\"");
}
OutputStream os = response.getOutputStream();
ZipOutputStream zos = new ZipOutputStream(os);
for (File f : files) {
//add files, it's working...
}
bis.close();
fis.close();
zos.closeEntry();
}
zos.flush();
zos.close();
os.flush();
os.close();
Currently to download I'm using a iframe, so I set src attribute to start download.
The download frame loads when call this function
function loadIDownloadFrame(url) {
document.getElementById("idownloadFrame").src=url;
}
But now, I need show a message after return the zip file without leaving current page. I need to know if the servlet returned the zip file.
I tried get iframe status with "window.frames['idownloadFrame'].document.readyState", but always status is "complete".
Anyone have any solutions?
I think you could directly refer to download link to mapped Servlet(which returns the downloadable binary). It would not change the page if you set appropriate header in the mapped servlet to return the binary, from the code snippet it looks like you are doing that already. Why do you have to have file download in a different iframe? You don't necessarily need that.
Where do you have to show the message? Like a JavaScript alert or something?