这里我试图使用java servlet从服务器读取pdf文件。下面的代码我正在获取文件路径,如果文件存在,然后尝试读取文件,但文件没有打开?
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();
答案 0 :(得分:2)
错误在这里:
response.setContentLength(fileToDownload.available());
InputStream#available()
不符合你(and the average Java starter)的想法。它不返回响应头表示的总内容长度。它返回可用于读取的字节数,而不会阻塞所有其他线程(即当前已放入硬件缓冲区的字节)。如果这低于实际文件大小,则客户端可能只是停止读取响应的其余部分。换句话说,客户端只获得PDF文件的一部分,因为您告诉客户端所需的部分具有完全给定的长度。
您需要构建一个普通java.io.File
并通过File#length()
获取文件大小。
这是一个完整的重写,也减少了旧的Java IO样板。这假设您至少使用Java 7(因为Java 6自2013年起就是EOL,没有人会期望您在Java 6之后的2年仍然存在):
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());
就是这样。请注意,上面的代码片段对于所有其他类型的文件也是可重用的。您可以通过<mime-mapping>
中的web.xml
条目管理未知内容类型。
另请注意,我正在将内容长度转换为字符串,因为setContentLength()
仅返回int
和File#length()
返回long
,如果文件是大于2GB。如果您已经使用Servlet 3.1(Tomcat 8等),请使用新的setContentLengthLong()
方法。
response.setContentLengthLong(file.length());