Reputation: 967
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();
Upvotes: 1
Views: 2892
Reputation: 1109502
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());
Upvotes: 2